go里基本数据、结构体、map、数组中值传递与地址传递分析

int类型的值传递与地值传递的两段代码:

package main

import (
	"fmt"
)

func main() {
	age := 15
	fmt.Println("原地址:")
	fmt.Println(&age)
	fmt.Println("值传递地址:")
	method(age)
	fmt.Println("指针传递地址:")
	method1(&age)
}

func method(age int) {
	fmt.Println(&age)
}

func method1(age *int) {
	fmt.Println(age)
}

打印结果为:
    1
    6

package main

import (
	"fmt"
)

func main() {
	age := 15
	fmt.Println("原地址:")
	fmt.Println(&age)
	fmt.Println("值传递地址:")
	method(age)
	fmt.Println("指针传递地址:")
	method1(&age)
}

func method(age int) {
	fmt.Println(&age)
}

func method1(age *int) {
	fmt.Println(age)
}

打印的结果如下:
    原地址:
    0xc04203c1d0
    值传递地址:
    0xc04203c1d8
    指针传递地址:
    0xc04203c1d0
结合两个例子打印的值与地址信息,可以看出int类型在值传递的时候是重新分配一个值过去,并不会改变原有的值,地址传递时是直接把当前的地址传过去,可以直接改变原有的值。

结构体类型的值传递与地值传递的两段代码:

package main

import (
	"fmt"
)

type person struct {
	age  int
	name string
}

func main() {
	per := person{
		age:  15,
		name: "jerry",
	}
	fmt.Println("值传递之前的信息:")
	fmt.Println(per)
	struct_method(per)
	fmt.Println("值传递之后的信息:")
	fmt.Println(per)

	per2 := person{
		age:  16,
		name: "dalianmao",
	}
	fmt.Println("地址传递之前的信息:")
	fmt.Println(per2)
	struct_method1(&per2)
	fmt.Println("地址传递之后的信息:")
	fmt.Println(per2)
}
func struct_method1(per *person) {
	per.age = 21
	per.name = "taoqi"
}
func struct_method(per person) {
	per.age = 20
	per.name = "tom"
}

结果是:
    值传递之前的信息:
    {15 jerry}
    值传递之后的信息:
    {15 jerry}
    地址传递之前的信息:
    {16 dalianmao}
    地址传递之后的信息:
    {21 taoqi}

package main

import (
	"fmt"
)

type person struct {
	age  int
	name string
}

func main() {
	per := person{
		age:  15,
		name: "jerry",
	}
	fmt.Println(fmt.Sprintf("值传递之前的地址为:%p", &per))

	dizhi(per)
	dizhi1(&per)
}
func dizhi(per person) {
	fmt.Println(fmt.Sprintf("值传递的地址为:%p", &per))
}
func dizhi1(per *person) {
	fmt.Println(fmt.Sprintf("地址传递的地址为:%p", per))
}

结果是:
    值传递之前的地址为:0xc042042400
    值传递的地址为:0xc042042460
    地址传递的地址为:0xc042042400

结合两个例子打印的值与地址信息,可见结构体类型值传递并不能改变结构体的信息,只有地址传递过可以,说明即便是结构体在值传递的时候也是复制一份传递过去。

package main

import (
	"fmt"
)

func main() {
	array := []int{1}
	fmt.Println(array)
	methodArrayValue(array)
	fmt.Println(array)
	methodArrayValue1(&array)
	fmt.Println(array)
}
func methodArrayValue(array []int) {
	array = append(array, 2)
}
func methodArrayValue1(array *[]int) {
	*array = append(*array, 3)
}

结果是:
    [1]
    [1]
    [1 3]

package main

import (
	"fmt"
)

func main() {
	array := []int{1}
	fmt.Println(fmt.Sprintf("传递之前的地址为:%p", &array))
	methodArrayValue(array)
	methodArrayValue1(&array)
}
func methodArrayValue(array []int) {
	fmt.Println(fmt.Sprintf("值传传递的地址为:%p", &array))
}
func methodArrayValue1(array *[]int) {
	fmt.Println(fmt.Sprintf("地址传递的地址为:%p", array))
}

结合两个例子打印的值与地址信息,可见数组在值传递时使用的也是重新复制一个数组传过去,而地址传递的时候直接把地址传了过去。

map的值传递与地址传递

package main

import (
	"fmt"
)

func main() {
	infos := map[string]string{
		"a": "A",
	}
	methodArrayValue(infos)
	fmt.Println(infos)
	methodArrayValue1(&infos)
	fmt.Println(infos)
}
func methodArrayValue(infos map[string]string) {
	infos["b"] = "B"
}
func methodArrayValue1(infos *map[string]string) {
	(*infos)["c"] = "C"
}

打印结果是:
    map[b:B a:A]
    map[c:C a:A b:B]

package main

import (
	"fmt"
)

func main() {
	infos := map[string]string{
		"a": "A",
	}
	fmt.Println(fmt.Sprintf("原地址是:%p", &infos))
	methodArrayValue(infos)
	methodArrayValue1(&infos)
}
func methodArrayValue(infos map[string]string) {
	fmt.Println(fmt.Sprintf("值传递的原地址是:%p", &infos))
}
func methodArrayValue1(infos *map[string]string) {
	fmt.Println(fmt.Sprintf("地址传递的地址是:%p", infos))
}

打印结果是:
    原地址是:0xc042004028
    值传递的原地址是:0xc042004038
    地址传递的地址是:0xc042004028

结合两个例子打印的值与地址信息,可见map在值传递时原来的值改变了,但是地址信息也改变了说明map在值传递时是重新分配了一个指针指向原来的值。

通过以上的例子可以看出,基本数据类型,结构体,数组在值传递的时候都是重新复制一份传递,而map在值值传递时则是重新分配了一个地址指向原来的值。如果想要提升效率使用地址传递,尤其在多属性的结构体与数组中,因为值传递需要把所有的信息都复制一份来使用;如果只想使用一下其值的信息但并不想改变原有的内容则可以使用值传递。

原文地址

转载于:https://my.oschina.net/wolf2leader/blog/1587795

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值