这可能是最全的golang的"=="比较规则了吧

Python014

这可能是最全的golang的"=="比较规则了吧,第1张

大家经常用"=="来比较两个变量是否相等。但是golang中的"=="有很多细节的地方,跟php是不一样的。很多时候不能直接用"=="来比较,编译器会直接报错。

golang中基本类型的比较规则和复合类型的不一致,先介绍下golang的变量类型:

golang中的基本类型

比较的两个变量类型必须相等。而且,golang没有隐式类型转换,比较的两个变量必须类型完全一样,类型别名也不行。如果要比较,先做类型转换再比较。

复合类型是逐个字段,逐个元素比较的。需要注意的是, array 或者struct中每个元素必须要是可比较的,如果某个array的元素 or struct的成员不能比较(比如是后面介绍的slice,map等),则此复合类型也不能比较。

逐个成员比较类型和值。每个对应成员的比较遵循基本类型变量的比较规则。

但是如果struct中有不可比较的成员类型时:

可以看到,struct中有slice这种不可比较的成员时,整个struct都不能做比较,即使没有对slice那个成员赋值(slice默认值为nil)

slice和map的比较规则比较奇怪,我们先说普通的变量引用类型&val和channel的比较规则。

引用类型变量存储的是某个变量的内存地址。所以引用类型变量的比较,判断的是这两个引用类型存储的是不是同一个变量。

上面看起来比较废话,但是得理解引用类型的含义。不然对判断规则还是不清楚。

slice类型不可比较,只能与零值nil做比较。

关于slice类型不可比较的原因,后面会专门写文章做讨论。

map类型和slice一样,不能比较,只能与nil做比较。

接口类型的变量,包含该接口变量存储的值和值的类型两部分组成,分别称为接口的动态类型和动态值。 只有动态类型和动态值都相同时,两个接口变量才相同:

而且接口的动态类型必须要是可比较的,如果不能比较(比如slice,map),则运行时会报panic。因为编译器在编译时无法获取接口的动态类型,所以编译能通过,但是运行时直接panic:

golang的func作为一等公民,也是一种类型,而且不可比较

上面说过,map和slice是不可比较类型,但是有没有特殊的方法来对slice和map做比较呢,有

reflect.DeepEqual函数可以用来比较两个任意类型的变量

对map类型做比较:

对slice类型做比较:

对struct类型做比较:

可以发现,只要变量的类型和值相同的话,reflect.DeepEqual比较的结果就为true

直接看用例:

结果为:

1, golang的类型再定义和类型别名

2,golang的slice和map为什么不可以比较

1, https://medium.com/golangspec/equality-in-golang-ff44da79b7f1

2, https://studygolang.com/articles/19144

3, https://juejin.im/post/5d5ff27d518825637965f3f3

所谓Go语言式的接口,就是不用显示声明类型T实现了接口I,只要类型T的公开方法完全满足接口I的要求,就可以把类型T的对象用在需要接口I的地方。这种做法的学名叫做Structural Typing,有人也把它看作是一种静态的Duck Typing。除了Go的接口以外,类似的东西也有比如Scala里的Traits等等。有人觉得这个特性很好,但我个人并不喜欢这种做法,所以在这里谈谈它的缺点。当然这跟动态语言静态语言的讨论类似,不能简单粗暴的下一个“好”或“不好”的结论。

我的观点:

Go的隐式接口Duck Typing确实不是新技术, 但是在主流静态编程语言中支持Duck Typing应该是很少的(不清楚目前是否只有Go语言支持).

静态类型和动态类型虽然没有绝对的好和不好, 但是每个都是有自己的优势的, 没有哪一个可以包办一切. 而Go是试图结合静态类型和动态类型(interface)各自的优势.

那么就从头谈起:什么是接口。其实通俗的讲,接口就是一个协议,规定了一组成员,例如.NET里的ICollection接口:

public interface ICollection {

int Count { get}

object SyncRoot { get}

bool IsSynchronized { get}

void CopyTo(Array array, int index)

}

这就是一个协议的全部了吗?事实并非如此,其实接口还规定了每个行为的“特征”。打个比方,这个接口的Count除了需要返回集合内元素的数目以外,还隐含了它需要在O(1)时间内返回这个要求。这样一个使用了ICollection接口的方法才能放心地使用Count属性来获取集合大小,才能在知道这些特征的情况下选用正确的算法来编写程序,而不用担心带来性能问题,这才能实现所谓的“面向接口编程”。当然这种“特征”并不但指“性能”上的,例如Count还包含了例如“不修改集合内容”这种看似十分自然的隐藏要求,这都是ICollection协议的一部分。

在正常的测试中,当我们需要进行接口测试时,通常使用接口调试工具,如postman进行接口测试

目前我在尝试使用Go语言进行接口测试,使用的库均为Go自带的库。

注:当前采用的接口为时事新闻接口,每天可以请求100次,需要的同学,可以自行使用。