Golang:三个常见的编程问题
每种语言都是个常唯一的。 这些常见的编程编程挑战的解决方案在Java(我以前最喜欢的编程语言)中非常不同。 而且,问题如果我敢说这一点,个常那么用Java更直观地解决这些问题。编程
Golang有解决这些问题的问题独特方法。 我下面列出的个常解决方案最初对我来说不是很直观,但是编程现在已经成为第二自然。 我不确定它们是问题否是"惯用的GO"-坦率地说,我不知道什么是个常惯用的GO。
也许会有更好的编程,不同的问题方式来解决这些问题-我很想听听您的想法。
因此,个常让我们深入研究编程挑战。编程
问题1:我需要维护一组"物品"。问题 但是,站群服务器哦,不,Golang没有" Set"数据结构。
解决方案之一:Golang没有"Set",但有"Map"。 映射的键集是一组唯一的项目。
您可以执行以下操作(https://play.golang.com/p/tayo3H5mi56):
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 BenchmarkOperator(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 doesnt 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的推论]
https://play.golang.com/p/0ac2HIyiJ9g
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进行递归比较。