Go语言编程笔记4:结构体和切片

本文是Go语言编程笔记的第四部分,主要介绍了Go语言中的结构体和切片。结构体的定义、方法及其与C/C++的区别进行了详细阐述。切片的原理、创建、扩容和细节被探讨,解释了切片作为动态数组的工作方式及其扩容机制。文章通过实例展示了Go语言中结构体和切片的使用方法和注意事项。
摘要由CSDN通过智能技术生成

Go语言编程笔记4:结构体和切片

image-20211108153040805

图源:wallpapercave.com

结构体

Go语言最主要使用的复合结构是结构体,我记得C和C++也是有结构体的,不过在C++中并不常用。事实上从语言继承的关系来说,Go语言与C语言是一脉相承的,所以又被称为类C语言。

定义

定义一个结构体就像是定义一个新的类型,只不过结构体一般会在结构体内部定义一些额外字段:

package main

type Pointer struct {
   
	x int
	y int
}

这里需要注意的是,虽然Go语言里的结构体可以类比为其它语言中的类,但是Go语言并没有“结构体命名时首字母大写”这样的命名惯例,相反,Go语言中,一个包中的结构体、变量、函数的首字母大写与否是由是否对包外部的调用可见来决定的,和这些命名所代表的类型完全没有关系。

声明一个结构体也很简单:

func main() {
   
	var p1 Pointer
}

同样的,如果是其它语言转过来的开发者,这里很容易会写为var pointer Pointer,虽然这里这样写并没有错,但是记住我前面说的,Go语言中并没有“结构体首字母一定会大写”这样的规则,所以很容易碰到同一个包内首字母小写的类型,所以别的语言里“临时对象使用首字母小写的类名命名”这样的习惯反而会带来一些麻烦。在Go语言中,一般会使用类型缩写来命名相应的变量,比如这里的var p1 Pointer,如果需要另外一个该类型的变量,可以命名为p2,以此类推。

需要特别说明的是,其它语言转过来的程序员很容易将上面的声明理解为声明了一个结构体Pointer的空指针,即p1 == nil,但这是不对的,因为在Go语言中结构体是一个值类型的变量,而不是引用类型。这点在Go语言编程笔记2:变量我有详细说明。所以这里实质上是会用0值来初始化p1,而结构体的0值实际上是结构体中的字段都用0值初始化后的一个结构体变量:

	var p1 Pointer
	fmt.Println(p1)
	// {0 0}

结构体没有其他语言中类那样的“构造函数”,事实上Go语言也完全没有传统OOP那样的继承关系,所以一个新定义的结构体是没有也不会有从别的地方继承来的默认方法的。

虽然我们可以用工厂方法添加一个结构体的初始化方法:

func newPointer(x, y int) Pointer {
   
	return Pointer{
   x: x, y: y}
}

但一般来说这么做意义不大,对于简单的结构体来说只要使用字面量直接初始化就够了:

	p1 = Pointer{
   x: 1, y: 1}
	fmt.Println(p1)
	// {1 1}

同样的,即使结构体内嵌套复杂的类型,也可以用类似的字面量来初始化:

type Pointers struct {
   
	pointers []Pointer
}
...省略
	var pts Pointers = Pointers{
   pointers: []Pointer{
   p1, {
   x: 1, y: 2}}}
	fmt.Println(pts)
	// {[{1 1} {1 2}]}

总的来说,相比其他语言中的类,Go语言偏向于使用简洁的方式来定义和初始化结构体。

方法

Go语言中通常只会给结构体添加方法,但实际上Go语言中,是可以给任何自定义类型添加方法的,即使其底层类型是基础类型:

type Celsius float64 //摄氏温度
func (c Celsius) String() string {
   
	return fmt.Sprintf("%.1fC", c)
}

type Fahrenheit float64 //华氏温度
func (f Fahrenheit) String() string {
   
	return fmt.Sprintf("%.1fF", f)
}

这里的例子来自Go语言编程笔记2:变量

Go语言的方法其实可以看做是“指定了一个接收者的函数”,而这个接收者就是方法实际调用时绑定的某个命名类型的变量。

这其实是一种函数式编程的风格和思路,熟悉Python的开发者应当不陌生。所以和Python类似,方法也是可以通过所绑定的类型名称来调用的:

	zero := Celsius(0)
	zeroString := Celsius.String(zero)
	fmt.Println
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值