go 指针类型
变量和内存地址
每个变量都有内存地址,可以说通过变量来操作对应大小的内存
var a int32 a = 100 fmt.Printf(“%d\n”, a) fmt.Printf(“%p\n”, &a)
通过&符号可以获取变量的地址
普通变量存储的是对应类型的值,这些类型就叫值类型
var b int32 b = 156 fmt.Printf(“%d\n”, b) fmt.Printf(“%p\n”, &b)
指针类型的变量存储的是一个地址,所以有叫指针类型或引用类型
var b int32 b = 156 var a *int32 a = &b
指针类型定义,var 变量名 *类型
package main import ( "fmt" ) func main() { b := 255 var a *int = &b fmt.Printf("Type of a is %T\n", a) fmt.Println("address of b is", a) }
指针类型变量的默认值为nil,也就是空地址
package main import ( "fmt" ) func main() { a := 25 var b *int if b == nil { fmt.Println("b is", b) b = &a fmt.Println("b after initialization is", b) } }
如果操作指针变量指向的地址里面的值呢?
通过* 符号可以获取指针变量指向的变量
package main import ( "fmt" ) func main() { b := 255 a := &b fmt.Println("address of b is", a) fmt.Println("value of b is",*a) }
通过指针修改变量的值
package main import ( "fmt" ) func main() { b := 255 a := &b fmt.Println("address of b is", a) fmt.Println("value of b is",*a) *a++ fmt.Println("new value of b is", b) }
举例
package main import "fmt" // 定义指针 func test1() { var a int = 100 var b *int fmt.Printf("a 的值为: %v a的内存地址是:%p a的类型是%t\n", a, &a, a) fmt.Printf("b 的值为: %v b的内存地址是:%p b的类型是%t\n", b, &b, b) b = &a fmt.Printf("b 的值为: %v b的内存地址是:%p b的类型是%t\n", b, &b, b) } /* a 的值为: 100 a的内存地址是:%!p(int=100) a的类型是%!t(int=100) b 的值为: <nil> b的内存地址是:0x0 b的类型是%!t(*int=<nil>) b 的值为: 0xc0000100a8 b的内存地址是:0xc0000100a8 b的类型是%!t(*int=0xc0000100a8) */ //控指针 func test2() { var a int = 100 var b *int fmt.Printf("b 的值为: %v b的内存地址是:%p b的类型是%t\n", b, &b, b) if b == nil { fmt.Println("b是一个空指针") b = &a } fmt.Printf("b 的值为: %v b的内存地址是:%p b的类型是%t\n", b, &b, b) } /* b 的值为: <nil> b的内存地址是:0xc000080018 b的类型是%!t(*int=<nil>) b是一个空指针 b 的值为: 0xc000058080 b的内存地址是:0xc000080018 b的类型是%!t(*int=0xc000058080) */ // 获取指针对应地址的值 func test3() { var a int = 100 var b *int b = &a fmt.Printf("b 的值为: %v b的内存地址是:%p b的类型是%t\n", b, &b, b) fmt.Printf("b 中存储的内存地址对应的值为%v\n", *b) } /* b 的值为: 0xc0000100a8 b的内存地址是:0xc000006028 b的类型是%!t(*int=0xc0000100a8) b 中存储的内存地址对应的值为100 */ // 改变指针存储地址对应的值 func test4() { var a int = 100 var b *int b = &a fmt.Printf("b 中存储的内存地址对应的值为%v\n", *b) fmt.Printf("a的值为%v\n", a) *b = 500 fmt.Printf("b 中存储的内存地址对应的值为%v\n", *b) fmt.Printf("a的值为%v\n", a) } /* b 中存储的内存地址对应的值为100 a的值为100 b 中存储的内存地址对应的值为500 a的值为500 */ func main() { // test1() // test2() test3() // test4() }
指针变量传参
package main import ( "fmt" ) func change(val *int) { *val = 55 }
func main() { a := 58 fmt.Println("value of a before function call is",a) b := &a change(b) fmt.Println("value of a after function call is", a) }
package main import ( "fmt" ) func modify(arr *[3]int) { (*arr)[0] = 90 } func main() { a := [3]int{89, 90, 91} modify(&a) fmt.Println(a) }
切片传参 切片是应用类型
package main import ( "fmt" ) func modify(sls []int) { sls[0] = 90 } func main() { a := [3]int{89, 90, 91} modify(a[:]) fmt.Println(a) }
package main import "fmt" func test1() { var a int = 100 var b *int b = &a fmt.Printf("a 的值为: %v a的内存地址是:%p a的类型是%t\n", a, a, a) fmt.Printf("b 中存储的内存地址对应的值为%v\n", *b) fmt.Printf("b 的值为: %v b的内存地址是:%p b的类型是%t\n", b, b, b) a = 200 fmt.Printf("a 的值为: %v a的内存地址是:%p a的类型是%t\n", a, a, a) fmt.Printf("b 中存储的内存地址对应的值为%v\n", *b) fmt.Printf("b 的值为: %v b的内存地址是:%p b的类型是%t\n", b, b, b) } /* a 的值为: 100 a的内存地址是:%!p(int=100) a的类型是%!t(int=100) b 中存储的内存地址对应的值为100 b 的值为: 0xc000058080 b的内存地址是:0xc000058080 b的类型是%!t(*int=0xc000058080) a 的值为: 200 a的内存地址是:%!p(int=200) a的类型是%!t(int=200) b 中存储的内存地址对应的值为200 b 的值为: 0xc000058080 b的内存地址是:0xc000058080 b的类型是%!t(*int=0xc000058080) */ func test2(a *int) { *a = 200 } func test3(a *[3]int) { (*a)[0] = 1000 } func test4(a []int){ a[0] = 123 } func modifytest() { // var a int = 2 // test2(&a) // fmt.Printf("修改后a的值为 %d", a) //修改后a的值为 200 // a := [3]int{1, 2, 3} // test3(&a) // fmt.Printf("修改后a的值为 %v", a) // 修改后a的值为 [1000 2 3] a:= [5]int{1,5,6,4,5} test4(a[:]) fmt.Printf("修改后a的值为 %v", a) // 修改后a的值为 [123 5 6 4 5] } func main() { // test1() modifytest() }
make 和 new
make用来分配引用类型的内存,比如 map、slice以及channel
new用来分配除引用类型的所有其他类型的内存,比如 int、数组等
package main import "fmt" func testNew() { var a *int = new(int) *a = 100 fmt.Printf("a=%v, a的内存地址%p, *a= v% *a的内存地址%p\n", a, a, *a, &(*a)) var b *[]int = new([]int) *b = make([]int, 5, 10) (*b)[0] = 10 fmt.Printf("b=%v, b的内存地址%p, *b= v% *b的内存地址%p\n", b, b, *b, &(*b)) } func main() { testNew() }
值拷贝和引用拷贝
值拷贝
package main import ( "fmt" ) func main() { var a int = 100 b := a }
引用拷贝
package main import ( "fmt" ) func main() { var a int = 100 var b *int = &a var c *int = b *c = 200 }
package main import "fmt" // 值拷贝 func test1() { var a int = 100 b := a fmt.Printf("a= %d, a的内存地址为%p\n", a, &a) fmt.Printf("b= %d, b的内存地址为%p\n", b, &b) } /* a= 100, a的内存地址为0xc000058080 b= 100, b的内存地址为0xc000058088 */ // 引用拷贝 func test2() { var a int = 10 var b *int b = &a fmt.Printf("a= %d, a的内存地址为%p\n", a, &a) fmt.Printf("b= %v, b的内存地址为%p *b=%d\n", b, &b, *b) *b = 100 fmt.Printf("a= %d, a的内存地址为%p\n", a, &a) fmt.Printf("b= %v, b的内存地址为%p *b=%d\n", b, &b, *b) } /* a= 10, a的内存地址为0xc000058080 b= 0xc000058080, b的内存地址为0xc000080018 *b=10 a= 100, a的内存地址为0xc000058080 b= 0xc000058080, b的内存地址为0xc000080018 *b=100 */ func test3() { var a [3]int = [3]int{1, 2, 3} var b *[3]int b = &a fmt.Printf("a= %d, a的内存地址为%p\n", a, &a) fmt.Printf("b= %v, b的内存地址为%p *b=%d\n", b, &b, *b) (*b)[1] = 100 fmt.Printf("a= %d, a的内存地址为%p\n", a, &a) fmt.Printf("b= %v, b的内存地址为%p *b=%d\n", b, &b, *b) } /* a= [1 2 3], a的内存地址为0xc0000560c0 b= &[1 2 3], b的内存地址为0xc000080018 *b=[1 2 3] a= [1 100 3], a的内存地址为0xc0000560c0 b= &[1 100 3], b的内存地址为0xc000080018 *b=[1 100 3] */ func main() { // test1() // test2() test3() }
练习 交换两个变量的值
package main import "fmt" func swap1(a int, b int) { fmt.Printf("swap 交换前 a= %d b=%d\n", a, b) a, b = b, a fmt.Printf("swap 交换后 a= %d b=%d\n", a, b) } func swap2(a *int, b *int) { fmt.Printf("swap 交换前 a= %d b=%d\n", *a, *b) *a, *b = *b, *a fmt.Printf("swap 交换后 a= %d b=%d\n", *a, *b) } func main() { var a int = 10 var b int = 20 // fmt.Printf("main 交换前 a= %d b=%d\n", a, b) // swap1(a, b) // fmt.Printf("main 交换后 a= %d b=%d\n", a, b) /* main 交换前 a= 10 b=20 swap 交换前 a= 10 b=20 swap 交换后 a= 20 b=10 main 交换后 a= 10 b=20 */ var c *int var d *int c = &a d = &b fmt.Printf("main 交换前 a= %d b=%d\n", a, b) swap2(c, d) fmt.Printf("main 交换后 a= %d b=%d\n", a, b) /* main 交换前 a= 10 b=20 swap 交换前 a= 10 b=20 swap 交换后 a= 20 b=10 main 交换后 a= 20 b=10 */ }