您的位置 首页 golang

Golang:三个常见的编程问题

还有三个不是很明显的Golang解决方案

每种语言都是唯一的。 这些常见的编程挑战的解决方案在 Java (我以前最喜欢的编程语言)中非常不同。 而且,如果我敢说这一点,那么用Java更直观地解决这些问题。

Golang有解决这些问题的独特方法。 我下面列出的解决方案最初对我来说不是很直观,但是现在已经成为第二自然。 我不确定它们是否是”惯用的GO”-坦率地说,我不知道什么是惯用的GO。

也许会有更好的,不同的方式来解决这些问题-我很想听听您的想法。

> Golang: Tips & Tricks

因此,让我们深入研究编程挑战。

问题1:我需要维护一组”物品”。 但是,哦,不,Golang没有” Set”数据结构。

解决方案之一:Golang没有”Set”,但有”Map”。 映射的键集是一组唯一的项目。

您可以执行以下操作():

 package main
import "fmt"
type Set struct { 
  m map[string]bool
}
func NewSet() Set { 
  m := make(map[string]bool) 
  return Set{m: m}
}

func (s *Set) Contains(val string) bool { 
  _, ok := s.m[val] 
  return ok
}

func (s *Set) Add(val string) { 
  s.m[val] = true
}

func (s *Set)  Remove (val string) { 
  delete(s.m, val)
}

func main() { 
  s := NewSet() 
  s.Add("foo") 
  fmt.Printf("s has foo: %t. s has bar: %t\n", s.Contains("foo"), s.Contains("bar")) 
  s.Remove("foo") 
  fmt.Printf("s has foo: %t. s has bar: %t\n", s.Contains("foo"), s.Contains("bar")) 
}  

将映射用作集合的基础数据结构的优点是,您仍然受益于超快速的映射键查找,基础哈希优化,并且最终编写的代码更少。

问题2:我需要比较两个值,但” ==”并不总是有效。

解决方案之一:让我们了解” ==”在哪里起作用,在哪里不起作用。

包含地图或切片的结构

 type ABC struct {
   a int
   b string
   c []int
}
Error:
invalid operation: a == b (struct containing []int cannot be compared)  

带指针的结构

好吧,实际上指针是可以比较的,但是它们并不总是能为您提供理想的结果。

 a, b := 1, 1
fmt.Println(&a == &b) // False  

输入reflect.DeepEqual

现在,这将可以按需工作(大多数情况下):

 //ABC - A simple type
type ABC struct {
   a int
   b string
   c []int
}
var a = ABC{a: 1, b: "10", c: []int{1, 2}}
var b = ABC{a: 1, b: "10", c: []int{1, 2}}
reflect.DeepEqual(a, b)
Example #2
a, b := 1, 1
fmt.Println(&a == &b) // False
fmt.Println(reflect.DeepEqual(&a, &b)) // True  

它将为您带来更好的结果-但是,如果您的结构中有浮点数或时间字段,则需要忽略。 您将需要编写自定义的equals方法

 //ABC - A simple type
type ABC struct {
   a int
   b string
   t time.Time // Ignore time while comparing to structs
}
var a = ABC{a: 1, b: "10", t: time.Now()}
var b = ABC{a: 1, b: "10", t: time.Now()}
fmt.Println(a == b, equals(a, b))
func equals(val1, val2 ABC) bool {
    return val1.a == val2.a && val1.b == val2.b
}  

除非您别无选择,否则您将不希望编写自定义的equals函数-但是,与==运算符相比,您应该更喜欢reflect.DeepEqual吗? 本质上,如果==将为true,则保证reflect.DeepEqual为true,反之则不为true。 因此,默认情况下可以使用reflect.DeepEqual。 除非您有性能限制,否则:

 func Benchmark op erator(t *testing.B) {
   for i := 0; i < t.N; i++ {
      if a == b {
      }
   }
}
func BenchmarkReflectDeep(t *testing.B) {
   for i := 0; i < t.N; i++ {
      if reflect.DeepEqual(a, b) {
      }
   }
}
BenchmarkOperator-8         44614131            24.8 ns/op         0 B/op          0 allocs/op
BenchmarkReflectDeep-8        823174          1558 ns/op          96 B/op          2 allocs/op  

” ==”比reflect.DeepEqual快。 更快。

问题#3:我需要使用结构作为映射的键-但我的结构包含要忽略的切片,指针或字段。

解决方案之一:Golang中的映射键评估使用==运算符,而不使用reflect.DeepEqual。

解决此问题的一种方法是使用自定义密钥创建逻辑。

 //Obvious solution that will not work
type A struct {
    i *int
}
i, j := 1, 1
a, b := A{i: &i}, A{i: &j}
m := map[A]bool{}
m[a] = true
_, ok := m[b]
fmt.Println(ok) // False key b doesn't exist in map m
//Custom keys- solution
func customKey(a A) int {
 return *a.i
}
i, j := 1, 1
a, b := A{i: &i}, A{i: &j}
 m := map[int]bool{}
 m[customKey(a)] = true
 _, ok := m[customKey(b)]
 fmt.Println(ok)// This will return true  

奖励问题:如何比较两个地图? [问题2和问题3的推论]

 key, val := "key", "val"
key1, val1 := "key", "val"
abc := map[*string]string{&key: val}
abc2 := map[*string]string{&key1: val1}
def := map[string]*string{key: &val}
def2 := map[string]*string{key1: &val1}
fmt.Println(reflect.DeepEqual(abc, abc2)) //false 
fmt.Println(reflect.DeepEqual(def, def2)) //true  

首先要注意的是,您不能通过==运算符比较地图。 您可以通过reflect.DeepEqual比较两个地图。 按照reflect.DeepEqual规则,将映射键与==运算符进行比较,并将值与reflect.DeepEqual进行递归比较。

(本文翻译自Saurabh Nayar的文章《Golang: Three common programming Problems》,参考:

文章来源:智云一二三科技

文章标题:Golang:三个常见的编程问题

文章地址:https://www.zhihuclub.com/97117.shtml

关于作者: 智云科技

热门文章

网站地图