Go语言实战笔记(七)| Go 类型

《Go语言实战》读书笔记,未完待续,欢迎扫码关注公众号flysnow_org,第一时间看后续笔记。

Go 语言是一种静态类型的编程语言,所以在编译器进行编译的时候,就要知道每个值的类型,这样编译器就知道要为这个值分配多少内存,并且知道这段分配的内存表示什么。

提前知道值的类型的好处有很多,比如编译器可以合理的使用这些值,可以进一步优化代码,提高执行的效率,减少bug等等。

基本类型

基本类型是Go语言自带的类型,比如数值类型、浮点类型、字符类型以及布尔类型,他们本质上是原始类型,也就是不可改变的,所以对他们进行操作,一般都会返回一个新创建的值,所以把这些值传递给函数时,其实传递的是一个值的副本。

func main() {
	name:="张三"
	fmt.Println(modify(name))
	fmt.Println(name)
}

func modify(s string) string{
	s=s+s
	return s
}
张三张三
张三

以上是一个操作字符串的例子,通过打印的结果,可以看到,本来name的值并没有被改变,也就是说,我们传递的时一个副本,并且返回一个新创建的字符串。

基本类型因为是拷贝的值,并且在对他进行操作的时候,生成的也是新创建的值,所以这些类型在多线程里是安全的,我们不用担心一个线程的修改影响了另外一个线程的数据。

引用类型

引用类型和原始的基本类型恰恰相反,它的修改可以影响到任何引用到它的变量。在Go语言中,引用类型有切片、map、接口、函数类型以及chan

引用类型之所以可以引用,是因为我们创建引用类型的变量,其实是一个标头值,标头值里包含一个指针,指向底层的数据结构,当我们在函数中传递引用类型时,其实传递的是这个标头值的副本,它所指向的底层结构并没有被复制传递,这也是引用类型传递高效的原因。

本质上,我们可以理解函数的传递都是值传递,只不过引用类型传递的是一个指向底层数据的指针,所以我们在操作的时候,可以修改共享的底层数据的值,进而影响到所有引用到这个共享底层数据的变量。

func main() {
	ages := map[string]int{"张三": 20}
	fmt.Println(ages)
	modify(ages)
	fmt.Println(ages)
}

func modify(m map[string]int) {
	m["张三"] = 10
}

这是一个很明显的修改引用类型的例子,函数modify的修改,会影响到原来变量ages的值。

结构类型

结构类型是用来描述一组值的,比如一个人有身高、体重、名字和年龄等,本质上是一种聚合型的数据类型。

type person struct {
	age int
	name string
}

要定义一个结构体的类型,通过type关键字和类型struct进行声明,以上我们就定义了一个结构体类型person,它有age,name这两个字段数据。

结构体类型定义好之后,就可以进行使用了,我们可以用过var关键字声明一个结构体类型的变量。

var p person

这种声明的方式,会对结构体person里的数据类型默认初始化,也就是使用它们类型的零值,如果要创建一个结构体变量并初始化其为零值时,这种var方式最常用。

如果我们需要指定非零值,就可以使用我们字面量方式了。

jim := person{10,"Jim"}

示例这种我们就为其指定了值,注意这个值的顺序很重要,必须和结构体里声明字段的顺序一致,当然我们也可以不按顺序,但是这时候我们必须为字段指定值。

jim := person{name:"Jim",age:10}

使用冒号:分开字段名和字段值即可,这样我们就不用严格的按照定义的顺序了。

除了基本的原始类型外,结构体内的值也可以是引用类型,或者自己定义的其他类型。具体选择类型,要根据实际情况,比如是否允许修改值本身,如果允许的话,可以选择引用类型,如果不允许的话,则需要使用基本类型。

函数传参是值传递,所以对于结构体来说也不例外,结构体传递的是其本身以及里面的值的拷贝。

func main() {
	jim := person{10,"Jim"}
	fmt.Println(jim)
	modify(jim)
	fmt.Println(jim)
}

func modify(p person) {
	p.age =p.age+10
}

type person struct {
	age int
	name string
}

以上示例的输出是一样的,所以我们可以验证传递的是值的副本。如果上面的例子我们要修改age的值可以通过传递结构体的指针,我们稍微改动下例子

func main() {
	jim := person{10,"Jim"}
	fmt.Println(jim)
	modify(&jim)
	fmt.Println(jim)
}

func modify(p *person) {
	p.age =p.age+10
}

type person struct {
	age int
	name string
}

这个例子的输出是

{10 Jim}
{20 Jim}

非常明显的,age的值已经被改变。如果结构体里有引用类型的值,比如map,那么我们即使传递的是结构体的值副本,如果修改这个map的话,原结构的对应的map值也会被修改,这里不再写例子,大家可以验证下。

自定义类型

Go语言支持我们自定义类型,比如刚刚上面的结构体类型,就是我们自定义的类型,这也是比较常用的自定义类型的方法。

另外一个自定义类型的方法是基于一个已有的类型,就是基于一个现有的类型创造新的类型,这种也是使用type关键字。

type Duration int64

我们在使用time这个包的时候,对于类型time.Duration应该非常熟悉,它其实就是基于int64 这个基本类型创建的新类型,来表示时间的间隔。

但是这里我们注意,虽然Duration是基于int64创建,觉得他们其实一样,比如都可以使用数字赋值。

type Duration int64

var i Duration = 100
var j int64 = 100

但是本质上,他们并不是同一种类型,所以对于Go这种强类型语言,他们是不能相互赋值的。

type Duration int64

var dur Duration
dur=int64(100)
fmt.Println(dur)

上面的例子,在编译的时候,会报类型转换的异常错误。

cannot use int64(100) (type int64) as type Duration in assignment

Go的编译器不会像Java的那样,帮我们做隐式的类型转换。

有时候,大家会迷茫,已经有了int64这些类型了,可以表示,还要基于他们创建新的类型做什么?其实这就是Go灵活的地方,我们可以使用自定义的类型做很多事情,比如添加方法,比如可以更明确的表示业务的含义等等,下一篇方法我们会讲到。

《Go语言实战》读书笔记,未完待续,欢迎扫码关注公众号flysnow_org,第一时间看后续笔记。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏lulianqi

IL指令详细

13230
来自专栏mukekeheart的iOS之旅

《JavaScript高级程序设计》学习笔记(1)

欢迎关注本人的微信公众号“前端小填填”,专注前端技术的基础和项目开发的学习。 首先,我将从《JavaScript高级程序设计》这本JavaScript学习者必看...

30140
来自专栏老司机的技术博客

golang学习笔记4:基本类型和运算符

布尔型的值只可以是常量 true 或者 false。一个简单的例子: var b bool = true 。两个类型相同的值可以使用相等 == 或者不等 != ...

31030
来自专栏Pythonista

Go语言基础

Go 程序可以由多个标记组成,可以是关键字,标识符,常量,字符串,符号。如以下 GO 语句由 6 个标记组成:

10630
来自专栏Java帮帮-微信公众号-技术文章全总结

【选择题】Java基础测试五(15道)

【选择题】Java基础测试五(15道) 56.下列哪个类的声明是正确的?( D ) A.abstract final class HI{} (final代...

36780
来自专栏程序员互动联盟

【专业技术】你必须注意的11个C++要点

下面的这些要点是对所有的C++程序员都适用的。我之所以说它们是最重要的,是因为这些要点中提到的是你通常在C++书中或网站上无法找到的。如:指向成员的指针,这是许...

28350
来自专栏chenjx85的技术专栏

leetcode-796-Rotate String

28660
来自专栏容器云生态

awk-grep-sed简单使用总结(正则表达式的应用)

正则表达式: 匹配一组字符: #[ns]a.\.xls  //[]用于限定字符;“.”用于匹配任意字符; \.用于转义"." 匹配到s/na*.xls  [n...

29990
来自专栏阿炬.NET

Reflector、reflexil、De4Dot、IL指令速查表

34850
来自专栏Python小屋

小议Python列表和元组中的元素地址连续性

众所周知,在Python中字典和集合依赖元素哈希表来存储,并不存在传统意义上的所谓元素“顺序”,当然,如果需要一个有序的字典可以使用collections模块提...

369100

扫码关注云+社区

领取腾讯云代金券