先上结论

golang的所有内置类型作为函数参数传递都是传值的方式(没有传递引用一说),需要注意的是:数组、slice和map作为函数参数时也是传值,但是如果对结构内元素进行的修改,修改的是原数据。如果是对其进行整体赋值,则不会修改原数据,相当于拷贝出一个新的临时变量。要想无论什么情况都修改原数据,可以通过传递指针参数实现。

来段实例代码

package main

import (
	"bytes"
	"fmt"
	"strings"
)

func f_1(a int) {
	a = 2
}

func f_1_1(a *int) {
	*a = 2
}

func f_2(s string) {
	s = "cba"
}

func f_2_1(s *string) {
	*s = "cba"
}

func f_3(v []string) {
	v[0] = "haha"
}

func f_3_1(v []string) {
	v = nil
}

func f_3_2(v *[]string) {
	*v = nil
}

func f_4(m map[int]int) {
	m[1] = 3
	m[3] = 1
}

func f_4_1(m map[int]int) {
	m = nil
}

func f_4_2(m *map[int]int) {
	*m = nil
}

func f_5(b []byte) {
	b[0] = 0x40
}

func f_5_1(b []byte) {
	b = bytes.Replace(b, []byte("1"), []byte("a"), -1)
}

func f_5_2(b *[]byte) {
	*b = bytes.Replace(*b, []byte("1"), []byte("a"), -1)
}

type why struct {
	s []string
}

func (ss why) SetV(s []string) {
	ss.s = s
}

func (ss *why) SetP(s []string) {
	ss.s = s
}

func (ss why) String() string {
	return strings.Join(ss.s, ",")
}

func main() {
	a := 1
	s := "abc"
	v := []string{"sd", "aa"}
	m := map[int]int{1: 1, 2: 2, 3: 3}
	f_1(a)
	f_2(s)
	f_3(v)
	f_4(m)
	fmt.Printf("%d,%s,%v,%v\n", a, s, v, m)
	f_3_1(v)
	f_4_1(m)
	fmt.Printf("%d,%s,%v,%v\n", a, s, v, m)
	f_1_1(&a)
	f_2_1(&s)
	f_3_2(&v)
	f_4_2(&m)
	fmt.Printf("%d,%s,%v,%v\n", a, s, v, m)
	b := []byte("12145178")
	f_5(b)
	fmt.Printf("%s\n", b)
	f_5_1(b)
	fmt.Printf("%s\n", b)
	f_5_2(&b)
	fmt.Printf("%s\n", b)
	ss := &why{}
	ss.SetV([]string{"abc", "efg"})
	fmt.Println(ss)
	ss.SetP([]string{"abc", "efg"})
	fmt.Println(ss)
}

输出如下

1,abc,[haha aa],map[1:3 2:2 3:1] slice和map值传递是可以修改原数据的,但基本数据类型不行
1,abc,[haha aa],map[1:3 2:2 3:1] 整体赋值不会修改原数据,值得注意的是map是无序的
2,cba,[],map[] 传递指针始终会修改原数据
@2145178 同上
@2145178 使用bytes.Replace实际上还是赋值,所以不会修改原数据
@2a45a78 使用指针传参就可以了
         类的成员函数定义为传值的方式,不会修改原数据(原数据为空)
abc,efg  类的成员函数定义为传指针的方式,可以修改原成员变量

成功: 进程退出代码 0.

现在弄明白了吗~