slice
和 map
在另一篇文章中填坑。
02_Golang开发_复合类型
slice
和map
在另一篇文章中填坑。
分类
指针
- 指针是一个代表着某个内存地址的值。
- 这个内存地址往往是在内存中存储的另一个变量的值的起始位置。
- Go 语言对指针的支持介于 Java 语言和 C/C++语言之间,它既没有想 Java 语言那样取消了代码对指针的直接操作的能力,也避免了 C/C++语言中由于对指针的滥用而造成的安全和可靠性问题。
基本操作
- Go 语言虽然保留了指针,但与其它编程语言不同的是:
- 默认值
nil
,没有 NULL 常量 - 操作符 "
&
" 取变量地址, "*
" 通过指针访问目标对象 - 不支持指针运算,不支持 "->" 运算符,
直接⽤ "." 访问目标成员
package main
import "fmt"
func main() {
var a int = 10 //声明一个变量,同时初始化
fmt.Printf("&a = %p\n", &a) //操作符 "&" 取变量地址
var p *int = nil //声明一个变量 p, 类型为 *int, 指针类型
p = &a
fmt.Println("p=", p)
fmt.Printf("a = %d, *p = %d\n", a, *p)
*p = 111 //*p 操作指针所指向的内存,即为 a
fmt.Printf("a = %d, *p = %d\n", a, *p)
}
//运行结果:
//&a = 0xc00001c098
//p= 0xc00001c098
//a = 10, *p = 10
//a = 111, *p = 111
new函数
- 表达式
new(T)
将创建一个 T 类型的匿名变量,所做的是为 T 类型的新值分配并清零一块内存空间,然后将这块内存空间的地址作为结果返回,而这个结果就是指向这个新的 T 类型 值的指针值,返回的指针类型为*T
。 - 我们只需使用
new()
函数,无需担心其内存的生命周期或怎样将其删除,因为 Go 语言的内存管理系统会帮我们打理一切。
package main
import "fmt"
func main() {
var p1 *int
p1 = new(int) //p1 为*int 类型, 指向匿名的 int 变量
fmt.Println("*p1 = ", *p1) //*p1 = 0
p2 := new(int) //p2 为*int 类型, 指向匿名的 int 变量
*p2 = 111
fmt.Println("*p2 = ", *p2) //*p1 = 111
}
指针做函数参数
package main
import "fmt"
func swap01(a, b int) {
a, b = b, a
fmt.Printf("swap01 a = %d, b = %d\n", a, b)
}
func swap02(x, y *int) {
*x, *y = *y, *x
}
func main() {
a := 10
b := 20
swap01(a, b) //值传递
//值传递a = 10, b = 20
fmt.Printf("值传递a = %d, b = %d\n", a, b)
swap02(&a, &b) //变量地址传递
//变量地址传递a = 20, b = 10
fmt.Printf("变量地址传递a = %d, b = %d\n", a, b)
}
数组
概述
- 数组是指一系列同一类型数据的集合。
- 数组中包含的每个数据被称为数组元素(element), 一个数组包含的元素个数被称为数组的长度。
- 数组⻓度必须是常量,且是类型的组成部分。
package main
func main() {
var n int = 10
var a [n]int //err, non-constant array bound n
var b [10]int //ok
}
操作数组
- 数组的每个元素可以通过索引下标来访问,索引下标的范围是从 0 开始到数组长度减 1 的位置。
package main
import "fmt"
func main() {
//数组的每个元素可以通过索引下标来访问,索引下标的范围是从 0 开始到数组长度减 1 的位置。
var a [10]int
for i := 0; i < 10; i++ {
a[i] = i + 1
fmt.Printf("a[%d] = %d\n", i, a[i])
}
fmt.Println("----------------------")
//range 具有两个返回值,第一个返回值是元素的数组下标,第二个返回值是元素的值
for i, v := range a {
fmt.Println("a[", i, "]=", v)
}
}
//a[0] = 1
//a[1] = 2
//a[2] = 3
//a[3] = 4
//a[4] = 5
//a[5] = 6
//a[6] = 7
//a[7] = 8
//a[8] = 9
//a[9] = 10
//----------------------
//a[ 0 ]= 1
//a[ 1 ]= 2
//a[ 2 ]= 3
//a[ 3 ]= 4
//a[ 4 ]= 5
//a[ 5 ]= 6
//a[ 6 ]= 7
//a[ 7 ]= 8
//a[ 8 ]= 9
//a[ 9 ]= 10
内置函数 len(长度) 和 cap(容量) 都返回数组⻓度 (元素数量)
func main() {
a := [10]int{}
fmt.Println(len(a), cap(a)) //10 10
}
初始化
func main() {
//初始化
a := [3]int{1, 2} // 未初始化元素值为 0
b := [...]int{1, 3, 2} // 通过初始化值确定数组长度
c := [5]int{2: 100, 4: 200} // 通过索引号初始化元素,未初始化元素值为 0
fmt.Println(a, b, c) //[1 2 0] [1 2 3] [0 0 100 0 200]
//支持多维数组
d := [4][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}}
e := [...][2]int{{10, 11}, {20, 21}, {30, 31}, {40, 41}} //第二维不能写"..."
f := [4][2]int{1: {20, 21}, 3: {40, 41}}
g := [4][2]int{1: {0: 20}, 3: {1: 41}}
fmt.Println(d, e, f, g)
}
相同类型的数组之间可以使用 == 或 != 进行比较,但不可以使用 < 或 >,也可以相互赋值
func main() {
//#### 相同类型的数组之间可以使用 == 或 != 进行比较,但不可以使用 < 或 >,也可以相互赋值
a := [3]int{1, 2, 3}
b := [3]int{1, 2, 3}
c := [3]int{1, 2}
fmt.Println(a == b, b == c) //true false
var d [3]int
d = a
fmt.Println(d) //[1 2 3]
}
在函数间传递数组
- 根据内存和性能来看,在函数间传递数组是一个开销很大的操作。
- 在函数之间传递变量时, 总是以值的方式传递的。
- 如果这个变量是一个数组,意味着整个数组,不管有多长,都会完整复制,并传递给函数。
package main
import "fmt"
func modify(array [5]int) {
array[0] = 10
//In modify(), array values: [10 2 3 4 5]
fmt.Println("In modify(), array values:", array)
}
func main() {
// 定义并初始化一个数组
array := [5]int{1, 2, 3, 4, 5}
modify(array) // 传递给一个函数,并试图在函数体内修改这个数组内容
//In main(), array values: [1 2 3 4 5]
fmt.Println("In main(), array values:", array)
}
数组指针做函数参数
// 数组指针做函数参数
func modify(array *[5]int) {
(*array)[0] = 10
//In modify(), array values: [10 2 3 4 5]
fmt.Println("In modify(), array values:", *array)
}
func main() {
array := [5]int{1, 2, 3, 4, 5} // 定义并初始化一个数组
modify(&array) // 数组指针
//In main(), array values: [10 2 3 4 5]
fmt.Println("In main(), array values:", array)
}
Comments | NOTHING