1. &和*
Go语言也有指针的概念,取地址用&
,根据地址取值用*
,Go里面的指针是没有C语言中复杂的。
记住&后面是取地址。*是解引用。取的是指针的值.
1
2
3
4
5
6
| n := 18
p := &n // 取内存地址,16进制的数,切片的值可以变,但是内存地址不会变,记住的是第一个元素的内存地址
fmt.Printf("%v,%T\n", p, p) // 0xc0000aa058, *int
// 根据指针地址得到变量值
a := *p
fmt.Println(a) // 18
|
2. new函数
1
2
3
4
5
6
7
8
9
| func main() {
var a *int // 这个是没有内存地址的,如果打印*a,会引发panic
fmt.Println(a) // <nil>
var a1 = new(int) // 是有内存地址的,new函数申请一个内存地址
fmt.Println(a1, *a1) // 0xc000014120 0
*a1 = 100
fmt.Println(a1, *a1) // 0xc000014120 100
}
|
3. new和make的区别
new和make的区别
- make和new都是用来申请内存的
- new很少用,一般用来给基本数据类型申请内存,string,int等返回的是对应类型的指针,*string,*int
- make用于也只能用于给slice、map、chan申请内存,make函数返回的是这三个类型本身,而不是他们的指针类型,因为这三张类型就是引用类型,所以就没必要返回他们的指针了。
4.注意点
我在编写的时候遇到这样一道代码, 这段代码取自go黑帽子编程
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| var (
flDomain = flag.String("domain", "", "The domain to perform guessing against.")
flWordlist = flag.String("wordlist", "", "The wordlist to use for guessing.")
flWorkerCount = flag.Int("c", 100, "The amount of workers to use.")
flServerAddr = flag.String("server", "8.8.8.8:53", "The DNS server to use.")
)
flag.Parse()
if *flDomain == "" || *flWordlist == "" {
fmt.Println("-domain and -wordlist are required")
os.Exit(1)
}
var results []result
fqdns := make(chan string, *flWorkerCount)
gather := make(chan []result)
tracker := make(chan empty)
|
flag函数返回的类型是*int
等。我们在用的时候,加了一个*
, 就是解引用。这样就能取到对应的值和类型了。下次遇到了不要再不会了!
操作指针的时候是解引用,记住下面的规律。
规律
1
2
3
4
| &int => *int
*(&int) => int
&(*int) => **int
*(&(&int)) => *int
|
下面的之所以*a1,是因为a1本身就是一个地址啊!*int类型的!
1
2
3
4
| var a1 = new(int) // 是有内存地址的,new函数申请一个内存地址
fmt.Println(a1, *a1)
*a1 = 100
fmt.Println(a1, *a1)
|
上面两种写法要记得!本质上都是 * (*int)
进行解引用。