Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

Go:学习笔记兼吐槽(3)

丹枫无迹 2019-01-30 08:25:00 阅读数:192 评论数:0 点赞数:0 收藏数:0

 

 

Go:学习笔记兼吐槽(1)

Go:学习笔记兼吐槽(2)

Go:学习笔记兼吐槽(3)

 

 

 

数组

Golang 中,数组是值类型。

数组的声明

var arr [10]int

数组的初始化

var arr1 [3]int = [3]int{1, 2, 3} var arr2 = [3]int{4, 5, 6} var arr3 = [...]int{7, 8, 9} var arr4 = [...]int{1: 100, 2: 200, 3: 300}

用 for-range 遍历数组

基本语法:for index, value := range 数组变量{ }

其中:

index为数组下标,

value是该下标位置的值。

长度是数组类型的一部分

长度是数组类型的一部分,就是说数组不可以脱离长度而存在。听起来不太明白,我们来看下面的一个示例就明白了,这真的是一个大坑。

假设,我们现在要写一个排序函数,C/# 中,我们会这样定义:public void Sort(int[] array) { }

但是,在 Golang 中,这是不行的。

func main() {     var arr [3]int = [3]int{1, 2, 3}     Sort(arr) } func Sort(array []int){ }

Sort(arr)这句编译就会报错:cannot use arr (type [3]int) as type []int in argument to Sort。因为

Sort函数的参数

array []int是一个切片,不是数组,将数组作为参数传给

Sort就会报类型不匹配。

如果一定需要以数组作为参数传递,

Sort的参数必须定义成数组,就是带上长度:func Sort(array [3]int){ }

这么定义这函数还有啥用?吐槽一万字…虽然有切片可以用来实现我们的功能,但是,数组就变得有点鸡肋了。

切片 slice

切片是引用类型,类似于 C/# 中的

list。内部维护一个数组,当追加元素超出切片容量时,切片自动扩容。(跟

list是一样的机制。)

切片的声明

var arr []int

切片的使用

//方法一: var arr1 [5]int = [5]int{1, 2, 3, 4, 5} slice1 := arr1[1: 3]    //这里的使用跟 Python 很像 //方法二: var slice2 []int = make([]int, 5, 10) //方法三: var slice3 []int = []int{1, 2, 3, 4, 5}

使用

make初始化切片,

make的三个参数依次为:切片数据类型,切片长度,切片容量。

给切片追加元素

//方法一:追加一个或多个同类型 var slice1 []int = make([]int, 5, 10) slice1 = append(slice1, 100, 200) fmt.Printf("%vn", slice1) //方法二:追加切片(只能是切片,不可以是数组) var slice2 []int = []int{1, 2, 3, 4, 5} slice1 = append(slice1, slice2...)    // 三个点不能少 fmt.Printf("%v", slice1)

append函数也很搞笑,其返回值必须赋值给一个切片,否则编译都过不了。如果一个切片调用

append追加元素后,又赋值给了自己(我们一般也是这么用的),则切片的地址不会发生改变(除非发生了扩容)。如果 切片 1 调用

append后赋值给了 切片 2,则 切片 1 保持未追加前的原样不变,另生成一个新的切片赋给 切片 2

示例:

var slice1 []int = make([]int, 5, 10) fmt.Printf("%v %pn", slice1, &slice1)    // [0 0 0 0 0] 0xc000004460 slice1 = append(slice1, 100) fmt.Printf("%v %pn", slice1, &slice1)    // [0 0 0 0 0 100] 0xc000004460 slice2 := append(slice1, 200) fmt.Printf("%v %pn", slice1, &slice1)    // [0 0 0 0 0 100] 0xc000004460 fmt.Printf("%v %pn", slice2, &slice2)    // [0 0 0 0 0 100 200] 0xc0000044e0

映射 map

就是字典。

map 的声明

var m map[int]string

map 的使用

// 方式一:使用 make 函数 m := make(map[int]string, 10) // 方式二:直接赋值 m := map[int]string{     1: "张三",     2: "李四", }

make方法的第一个参数是 map 的数据类型,第二个参数是初始容量。

注意,如果是方式二直接赋值,最后一个 key-value 后面也要加逗号。

删除元素

delete(map, key)

参数:

  • map:要删除元素的 map
  • key:要删除的 key,当 key 在 map 中不存在时,不进行任何操作,也不报错。

Golang 中 map 没有类似其他语言中的

clear方法,如果要一次性删除全部元素,可遍历 map 逐一删除,或者重新

make一下使其指向一个新的内存空间。

查找元素

val, finded := m[1] if finded{     fmt.Println(val) }

遍历元素

只能用 for-range 遍历for k, v := range m{     fmt.Printf("%v: %vn", k, v) }

结构体 struct

  • Golang 中没有类(class),Go 中的结构体(struct)和其他语言中的类有同等的地位。可以理解为 Golang 是基于 struct 来实现面向对象。
  • 结构体是值类型。结构体的所有字段在内存中是连续的。

结构体的声明

type 结构体名称 struct{     field1 type     field2 type }

结构体的使用

type Person struct{     Name string     Age int } // 方式一: p1 := Person{} p1.Name = "Tom" p1.Age = 10 // 方式二 p2 := Person{"Jerry", 5} // 方式三 p3 := Person{Name: "张三", Age: 30} // 或p3 := Person{ Name: "张三",  Age: 30,        // 注意这里要加逗号,否则会被默认加上分号 }

结构体指针

// 方式一: var person1 /Person = new(Person) (/person1).Name = "Tom" (/person1).Age = 10 fmt.Println(/person1) // 方式二: person2 := new(Person) person2.Name = "Tom" person2.Age = 10 fmt.Println(/person2) // 方式三: var person3 /Person = &Person{"Jerry", 5} fmt.Println(/*person3)

这三种方式定义的都是结构体指针,因为是指针,所以给字段赋值的标准方式应该是方式一的写法,但是 Go 的设计者为了程序员使用方便,给出了一个语法糖,使

(/*person1).Name = "Tom"简化为

person1.Name = "Tom",即方式二的写法,编译时,会自动加上取值运算。而方式三的写法可以直接赋值。

结构体标签

struct 的每个字段上可以定义一个标签(tag),该标签可以通过反射机制获取,最常见的使用场景就是序列化和反序列化。type Person struct{     Name string json:"name"     Age int json:"age" } p := Person{"张三", 30} jsonStr, err := json.Marshal(p) if err == nil {     fmt.Println(string(jsonStr)) // {"name":"张三","age":30} }

自定义数据类型

为了简化数据类型定义,Golang 支持自定义数据类型。

基本语法:type 自定义数据类型名 数据类型  // 相当于起了一个别名

示例:

type myint int  //这时 myint 就等价于 int,但是 Go 会认为他们还是两个类型 type mySum func(int, int) int  //这时 mySum 就等价于一个函数类型

自定义数据类型跟原类型虽然在我们的理解上是一样的,但是 Golang 会认为它们是两种不同的数据类型。这导致这两种类型是无法直接进行比较的,必须强转。

版权声明
本文为[丹枫无迹]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/gl1573/p/10334847.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;