Go语言基础学习 指针和地址
有几个很不错的学习教程,感觉很不错
- GitHub开源go学习教程 https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/preface.md
- B站教程 https://space.bilibili.com/322210472/channel/detail?cid=108884
- Go语言程序设计中文版 https://docs.hacknode.org/gopl-zh/ch2/ch2-03.html
最后就是go官网了
- https://golang.org/doc/
- go官网练习 https://tour.golang.org/list
指针和地址
上来咱就讲指针和地址,go各种数据类型,字符串,数组,map看看语法,多敲敲
可以参考 https://docs.hacknode.org/gopl-zh/ch2/ch2-03.html 这一章节。
可以参考下知乎问题为什么要有指针
我现在的理解就是, 指针通俗来讲就是内存地址,直接通过内存地址修改某个值,这是最直接,也是效率最高的。
下面是练习指针代码,给指针赋值地址 通过地址取值
如果用“var x int”声明语句声明一个x变量,那么&x表达式(取x变量的内存地址)将产生一个指向该整数变量的指针,指针对应的数据类型是*int,指针被称之为“指向int类型的指针”。
package main
import "fmt"
func main() {
a := 123
fmt.Println(a)
var b *int // 定义b为指针类型
b = &a // & 取地址符号
*b = 666 // 表示的就是值
fmt.Println(a, &a, b, *b, &*b)
// 函数传入地址, 函数内部可以修改值
changeA1(&a) // &取地址 指向该变量的指针 所以函数用 *int接收
fmt.Println(a) // 777
changeA2(a)
fmt.Println(a) // 还是777 不会变成888
// 同理其他 数据类型 数组 map struct等 可以定义指针
}
func changeA1(z *int) {
// 使用指针可以改变原来的值
*z = 777
}
func changeA2(n int) {
// 不能改变原来的值
n = 888
}
计数的例子
import "fmt"
func counter(i *int){
*i ++
}
func main() {
p := 1
counter(&p)
counter(&p)
counter(&p)
fmt.Println(p) // 输出 4
}
指针类型的赋值
package main
import "fmt"
func counter(i *int){
*i ++
}
func main() {
// 创建一个 int 类型的值
n := 1
//p := new(int) new只是一个新的语法糖 相当于 var p *int
var p *int
// 把n变量的地址 赋值给 int指针类型变量 p
p = &n
// 传入n的地址 (n的地址指向 n变量的指针)
counter(&n)
// 输出 int指针 类型的变量 p 的值
fmt.Println(*p) // 2
// *p 和 n 地址指向 同一地址
fmt.Println(&(*p) == &n) // true
}
复杂数据类型的指针
package main
import (
"fmt"
)
func main() {
a := [3]string{"a", "b", "c"}
// 定义一个数组指针 外部是一个指针 内部是元素
var b *[3]string
b = &a
// 先通过*b取出array值 然后修改 array里面的值
(*b)[0] = "zzz"
fmt.Println(a)
c := [3]string{"q", "w", "e"}
// 定义一个指针数组 外部是array 里面元素是指针
d := [3]*string{&c[0], &c[1], &c[2]}
fmt.Println(c)
*d[0] = "qqqqq"
fmt.Println(d, *d[0])
fmt.Println(c)
// 定义一个map key为值 value为 字符串指针
e := map[string]*string{}
f := "r"
e["a"] = &f
fmt.Println("e是", e)
// 定义一个map key value都为 字符串指针
g := map[*string]*string{}
h := "t"
i := "y"
// 字符串指针 key赋予地址 value也赋予地址
g[&h] = &i
fmt.Println("g是", g, "取value值", *g[&h])
}
结构体指针
package main
import "fmt"
// 定义一个结构体
type Cat struct {
name string
color string
sex bool
}
func main() {
// 实例化
tom := Cat{
name:"Tom",
color:"white",
sex: true,
}
fmt.Println(tom)
// 定义一个结构体指针
var tom2 *Cat
// 地址赋值给结构体指针
tom2 = &tom
fmt.Println(tom)
// 结构体指针改变 值
(*tom2).name = "old tom"
fmt.Println(tom)
}
传入指针和值的最直接的区别。
package main
import "fmt"
type Foo struct {
Name string `json:"name"`
}
// 传入指针 直接传入地址修改原来的值
func (f *Foo) ModifyName(a string){
f.Name = a
}
// 传入值 相当于copy 对原来的值不影响
func (f Foo) NotModifyName(a string){
f.Name = a
}
func main() {
//fmt.Printf("Hello World")
f := Foo{Name:"Nike"}
// 不能修改f对象的值
f.NotModifyName("not new name")
// 可以修改对象的值
//f.ModifyName("new name")
fmt.Println(f)
}
更多练习代码关注个人博客
个人博客 https://www.charmcode.cn/article/2020-07-26_Go_lets_go