聊聊 Golang、C、C++ 中的指针传递

84 阅读2分钟

先玩个小游戏: 三段代码,分别是C、C++、Golang,猜输出结果

先看C

#include <stdio.h>

struct Simple {
	int Number;
};

void SetF(struct Simple *s){
	printf("SetF---------%d\n", s->Number);

	struct Simple s_v2;
	s_v2.Number=1;
	s = &s_v2;
	printf("SetF---------%d\n", s->Number);
}

void SetF2(struct Simple *s){
	printf("SetF2---------%d\n", s->Number);

	struct Simple s_v2;
	s_v2.Number=2;
	*s = s_v2;
	printf("SetF2---------%d\n", s->Number);
}

int main()
{
    struct Simple testS;
	printf("Simple=%d\n", testS.Number);
	
    SetF(&testS);
    printf("SetF=%d\n", testS.Number);
	
	
	SetF2(&testS);
    printf("SetF2=%d\n", testS.Number);
		
    return 0;
}

结果如下:

Simple=0
SetF---------0
SetF---------1
SetF=0
SetF2---------0
SetF2---------2
SetF2=2

猜对了吗?

继续看C++

#include <iostream>
using namespace std;


struct Simple {
	int Number;
};

void SetF(struct Simple &s){
	printf("SetF---------%d\n", s.Number);
	s.Number=1;
	printf("SetF---------%d\n", s.Number);
	
}

void SetF2(struct Simple &s){
	printf("SetF2---------%d\n", s.Number);

	struct Simple s_v2;
	s_v2.Number=2;
	s = s_v2;
	printf("SetF2---------%d\n", s.Number);
}

int main()
{
	struct Simple s;
	s.Number=0;
  
	printf("Simple=%d\n", s.Number);
    SetF(s);
    printf("Simple=%d\n", s.Number);
	
	SetF2(s);
    printf("Simple=%d\n", s.Number);
    return 0;
}

运行结果如下:


Simple=0
SetF---------0
SetF---------1
Simple=1
SetF2---------1
SetF2---------2
Simple=2

猜到了吗?

最后看看GO

package main

import (
    "fmt"
    "testing"
)

type Simple struct {
    number int
}

func SetF(s *Simple) {
    s = &Simple{
       number: 1,
    }
}

func SetF2(s *Simple) {
    *s = Simple{
       number: 2,
    }
}

func SetF3(s *Simple) {
    s.number = 3
}

func Test1(t *testing.T) {
    var testS *Simple
    SetF(testS)
    fmt.Printf("type of c:%T\n", testS)
    fmt.Printf("value of c:%v\n", testS)

}

func Test1_1(t *testing.T) {
    var testS Simple
    SetF(&testS)
    fmt.Printf("type of c:%T\n", testS)
    fmt.Printf("value of c:%v\n", testS)

}

func Test2(t *testing.T) {
    var testS *Simple
    SetF2(testS)
    fmt.Printf("type of c:%T\n", testS)
    fmt.Printf("value of c:%v\n", testS)
}
func Test2_1(t *testing.T) {
    var testS Simple
    SetF2(&testS)
    fmt.Printf("type of c:%T\n", testS)
    fmt.Printf("value of c:%v\n", testS)
}

func Test3(t *testing.T) {
    var testS *Simple
    SetF3(testS)
    fmt.Printf("type of c:%T\n", testS)
    fmt.Printf("value of c:%v\n", testS)
}

func Test3_1(t *testing.T) {
    var testS Simple
    SetF3(&testS)
    fmt.Printf("type of c:%T\n", testS)
    fmt.Printf("value of c:%v\n", testS)
}

运行结果:

1:
type of c:*main.Simple
value of c:<nil>

1-2:
type of c:main.Simple
value of c:{0}

2:
panic: runtime error: invalid memory address or nil pointer dereference

2-1:
type of c:main.Simple
value of c:{2}

3:
panic: runtime error: invalid memory address or nil pointer dereference

3-1:
type of c:main.Simple
value of c:{3}

请在评论区留下你的成绩

从上面的几段代码中可以看出:

Golang 和 C 一脉相承,均没有引用传递,所有传递均为值传递。


package unsafe

type ArbitraryType int

type Pointer *ArbitraryType

看源码,Go的指针,其实就是int值。

所以子函数拿到的都是一个地址

  1. 修改这个地址本身没有任何意义
  2. 修改这个地址指向的内容才有意义
  3. 指向的内容如果是nil,会panic