Golang:三个常见的编程问题

开发 后端
常见的编程挑战的解决方案在Java(我以前最喜欢的编程语言)中非常不同。 而且,如果我敢说这一点,那么用Java更直观地解决这些问题。Golang有解决这些问题的独特方法。

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

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

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

[[332156]]

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

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

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

您可以执行以下操作(https://play.golang.com/p/tayo3H5mi56):

  1. package main 
  2. import "fmt" 
  3. type Set struct {  
  4.   m map[string]bool 
  5. func NewSet() Set {  
  6.   m :make(map[string]bool)  
  7.   return Set{m: m} 
  8.  
  9. func (s *Set) Contains(val string) bool {  
  10.   _, ok :s.m[val]  
  11.   return ok 
  12.  
  13. func (s *Set) Add(val string) {  
  14.   s.m[val] = true 
  15.  
  16. func (s *Set) Remove(val string) {  
  17.   delete(s.m, val) 
  18.  
  19. func main() {  
  20.   s :NewSet()  
  21.   s.Add("foo")  
  22.   fmt.Printf("s has foo: %t. s has bar: %t\n", s.Contains("foo"), s.Contains("bar"))  
  23.   s.Remove("foo")  
  24.   fmt.Printf("s has foo: %t. s has bar: %t\n", s.Contains("foo"), s.Contains("bar"))  

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

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

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

包含地图或切片的结构

  1. type ABC struct { 
  2.    a int 
  3.    b string 
  4.    c []int 
  5. Error: 
  6. invalid operation: a == b (struct containing []int cannot be compared) 

带指针的结构。

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

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

输入reflect.DeepEqual

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

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

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

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

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

  1. func BenchmarkOperator(t *testing.B) { 
  2.    for i :0; i < t.N; i++ { 
  3.       if a == b { 
  4.       } 
  5.    } 
  6. func BenchmarkReflectDeep(t *testing.B) { 
  7.    for i :0; i < t.N; i++ { 
  8.       if reflect.DeepEqual(a, b) { 
  9.       } 
  10.    } 
  11. BenchmarkOperator-8         44614131            24.8 ns/op         0 B/op          0 allocs/op 
  12. BenchmarkReflectDeep-8        823174          1558 ns/op          96 B/op          2 allocs/op 

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

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

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

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

  1. //Obvious solution that will not work 
  2. type A struct { 
  3.     i *int 
  4. i, j :1, 1 
  5. a, b :A{i: &i}, A{i: &j} 
  6. :map[A]bool{} 
  7. m[a] = true 
  8. _, ok :m[b] 
  9. fmt.Println(ok) // False key b doesn't exist in map m 
  10. //Custom keys- solution 
  11. func customKey(a A) int { 
  12.  return *a.i 
  13. i, j :1, 1 
  14. a, b :A{i: &i}, A{i: &j} 
  15.  m :map[int]bool{} 
  16.  m[customKey(a)] = true 
  17.  _, ok :m[customKey(b)] 
  18.  fmt.Println(ok)// This will return true 

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

https://play.golang.com/p/0ac2HIyiJ9g

  1. key, val :"key", "val" 
  2. key1, val1 :"key", "val" 
  3. abc :map[*string]string{&key: val} 
  4. abc2 :map[*string]string{&key1: val1} 
  5. def :map[string]*string{key: &val} 
  6. def2 :map[string]*string{key1: &val1} 
  7. fmt.Println(reflect.DeepEqual(abc, abc2)) //false  
  8. fmt.Println(reflect.DeepEqual(def, def2)) //true 

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

 

责任编辑:赵宁宁 来源: 今日头条
相关推荐

2024-03-19 14:14:27

线程开发

2022-05-27 12:40:25

前端测试项目

2021-10-13 06:59:03

Python技巧编程

2024-01-09 15:37:46

2022-10-13 14:15:35

商业智能大数据工具

2020-10-09 06:54:22

通信专业误区

2011-12-20 10:41:36

程序员

2018-07-11 05:24:05

机器学习人工智能数据

2022-03-08 09:31:48

云配置云安全

2009-08-03 13:43:02

C#日历控件

2010-10-26 13:45:01

Oracle数据库备份

2021-10-08 08:49:52

VMware虚拟实验室虚拟化

2011-01-19 13:11:25

Zimbra白名单证书

2021-09-16 15:06:33

漏洞管理漏洞网络攻击

2017-02-22 14:24:33

编程IT能力

2023-04-26 11:14:11

IT领导者远程工作

2010-09-27 16:48:34

2023-01-28 09:50:43

数字化转型企业

2022-03-16 11:04:57

数字化转型企业业务

2020-10-20 06:45:48

编程高并发
点赞
收藏

51CTO技术栈公众号