1.链表改变头指针和返回投指针
package main
import "fmt"
type Node struct {
num int
next *Node
}
func main() {
n := 0
fmt.Scan(&n)
head := &Node{-1, nil}
tmp := head
for i := 1; i <= n; i++ {
tmp.next = &Node{i, nil}
tmp = tmp.next
}
head = head.next
reverse(head)
//head = reverse1(head)
Print(head)
}
func reverse(head *Node) {
first := head
second := head.next
head.next = nil
for second != nil {
tmp := second
second = second.next
tmp.next = first
first = tmp
}
head = first
}
func reverse1(head *Node) *Node {
first := head
second := head.next
head.next = nil
for second != nil {
tmp := second
second = second.next
tmp.next = first
first = tmp
}
head = first
return head
}
func Print(head *Node) {
tmp := head
for tmp != nil {
fmt.Printf("%d ", tmp.num)
tmp = tmp.next
}
fmt.Println()
}
上面的区别主要在于我是直接改编原头指针的指向还是返回一个新指针后在main函数中改变指向
通过编译分析发现head首先就是main函数中的地址,通过赋值之后指向最后一个元素,但是函数返回之后还是指向第一个元素,也就是说,**在函数内部改变指针的指向是没有用的**
这么说go的指针是值传递,不是引用传递?
事实上说,go语言是没有引用传递的,go语言之所以可以达到引用传递的效果,实际上是这些数据结构底层的指针指向同一片内存地址,从而达到看似引用传递的效果.
所以说在函数内部不能修改指针的指向?
是的,指针本质上就是一个内存地址,也就是一个8位或者4位的二进制数,这个地址在函数传递的时侯其实也是传递的一份副本,只不过指向同一片内存,对这个内存的修改对其他函数也可见.例如,如果切片在函数中发送了阔容,函数外的切片孩是不会变化的
package main
import "fmt"
func main() {
s := make([]int, 1, 3)
//s := make([]int, 1, 20)
fmt.Printf("cap:%d len:%d arrs:%p \n", cap(s), len(s), &s[0])
extendSlice(s)
fmt.Printf("cap:%d len:%d arrs:%p \n", cap(s), len(s), &s[0])
}
func extendSlice(s []int) {
fmt.Printf("cap:%d len:%d arrs:%p \n", cap(s), len(s), &s[0])
for i := 0; i < 7; i++ {
s = append(s, i)
}
fmt.Printf("cap:%d len:%d arrs:%p \n", cap(s), len(s), &s[0])
}
//stdin
//cap:3 len:1 arrs:0xc00001c198
//cap:3 len:1 arrs:0xc00001c198
//cap:12 len:8 arrs:0xc000028240
//cap:3 len:1 arrs:0xc00001c198
既然说到这里了,go语言还有个unsafe.Pointer,这个有什么区别?
首先看看unsafe.Pointer的结构
//这里就不放官方解释了,感兴趣的去看源码
//大概意思是unsafe.Pointer可以表示任意类型的指针,也可以转成任意类型,并绕过类型检察读写其内存值
type Pointer *ArbitraryType
// ArbitraryType is here for the purposes of documentation only and is not actually
// part of the unsafe package. It represents the type of an arbitrary Go expression.
//大概意思是这个结构体属于任意类型
type ArbitraryType int
unsafe.Pointer的作用主要就是跳过类型检测修改一些数据,但是在实际的开发中并不建议这样做,因为不好维护而且容易出bug