综合编程

Go语言入门(六)结构体后续&指针

微信扫一扫,分享到朋友圈

Go语言入门(六)结构体后续&指针

结构体后续&指针

指针

变量和内存地址

  • 每个变量都有内存地址,可以通过变量来操作对应的内存
func varMem() {
var a int32 = 100
fmt.Printf("addr %pn",&a)
}
func pointMem() {
var b int32
b = 32
var a *int32
fmt.Printf("addr of a:%vntype of a %Tn",a,a)  //取出a的地址和类型
a = &b
fmt.Printf("a %d addr:%pntype of a:%Tnb %d addr %pn",*a,&a,a,b,&b)
}

指针的定义与取值

&
*
func pointMem1()  {
var a *int
b := 200
a = &b
*a = 400
fmt.Printf("a=%v,adda=%p,type a=%#Tnb=%v,addb=%p,type b=%#Tn",*a,a,a,b,&b)
}
func pointMem2()  {
var a *int
var b int = 100
if a == nil {
a = &b
}
fmt.Printf("addr a=%p,value a=%dnaddr b=%p,value b=%dn",a,*a,&b,b)
}
  • 小例子

猜输出

func modify(a int) {
a = 1000
}
func modify2(a *int) {
fmt.Printf("address of a: %pn",&a)
*a = 1000
}
func main() {
var b int = 100
modify(b)
fmt.Printf("b=%dn",b)
var p *int = &b
fmt.Printf("address of p: %pn",&p)
modify2(&b)
fmt.Printf("b=%dn",b)
}

指针变量传参

  • 修改数组
func modifyArray(arr *[3]int) {
//经过修改之后的arr,成了引用类型而不是值类型,因为其内存地址保持一致
fmt.Printf("2. arr=%#v,address=%pn",*arr,&arr)
(*arr)[0] = 90
fmt.Printf("3. arr=%#v,address=%pn",*arr,&arr)
}
func main() {
a := [3]int{89,90,91}
modifyArray(&a)
fmt.Printf("1. arr=%#v,addreess=%pn",a,&a)
}
  • 切片传参: 切片是引用类型,底层是指针,所以可以直接修改
func modifySlice(a []int) {
fmt.Printf("2.slice=%v,address=%pn",a,&a)
a[0] = 90
fmt.Printf("3.slice=%v,address=%pn",a,&a)
}
func main() {
a := []int{89,90,91}
modifySlice(a)
fmt.Printf("1. silce=%#v,address=%pn",a,&a)
}

指针类型

  • make用来分配引用类型的内存,例如:map,channel,slice
  • new用来分配除引用类型的所有其他类型的内存,例如: int,数组等
func newPoints() {
var p *int = new(int)
fmt.Printf("p=%v,address=%pn",p,&p)
*p = 100
fmt.Printf("p=%v,address=%pn",*p,&p)
}
type User struct {
Name     string
Age      int
}
func StructPoint() {
var pUser *User = new(User)
pUser.Name = "alex"
pUser.Age = 19
fmt.Printf("user:%vn",*pUser)
}
func newSlice() {
var p *[]int = new([]int)
*p = make([]int,10)
(*p)[0] = 100
fmt.Printf("p=%v,address=%pn",*p,&p)
}
func newMap() {
var p *map[string]int = new(map[string]int)
*p = make(map[string]int)
(*p)["key1"] = 100
(*p)["key2"] = 200
fmt.Printf("p=%v,address=%pn",*p,&p)
}
func main() {
newPoints()
StructPoint()
newSlice()
newMap()
}

值拷贝和引用拷贝

  • 值拷贝就是将拷贝对象重新开辟内存空间,然后将拷贝值放入新的内存空间
  • 引用拷贝就是拷贝内存地址,指向同一个值
func valueCopy() {
a := 10
b := a
fmt.Printf("a=%d,address a=%p,b=%d,address b=%pn",a,&a,b,&b)
c := 10
d := &c
fmt.Printf("c=%d,address c=%p,d=%d,address d=%pn",c,&c,*d,d)
}

面向对象编程

方法的定义

  • 跟其他语言不一样,go的方法采用另外一种方式实现
  • Go的方法是在函数前面加上一个接受者,这样编译器就知道这个方法属于哪个类型了
type Students struct {
Name string
Age  int
}
//定义了值类型为Students的方法
func (s Students) GetName() string{
return s.Name
}
//修改需要指针类型的方法
func (s *Students) SetName(name string) {
s.Name = name
}
func main() {
var s1 Students  = Students{
Name:"s1",
Age:12,
}
name := s1.GetName()
fmt.Printf("name=%sn",name)
//修改name
s1.SetName("s2")
name = s1.GetName()
fmt.Printf("name=%sn",name)
}
  • 可以为当前包内的任何类型增加方法
//定义一个integer类型
type Integer int64
func (i Integer) Print()  {
fmt.Printf("i=%dn",i)
}
func (i *Integer) Set(b int64) {
*i = Integer(b)
}
func main() {
var a Integer
a = 1000
fmt.Printf("a=%dn",a)
var b int64 = 500
a = Integer(b)
fmt.Printf("a=%dn",a)
a.Print()
a.Set(10000)
a.Print()
}
  • 函数不属于任何类型,方法属于特定类型
  • 指针类型作为接受者
  • 值类型和指针类型作为接受者的区别

    • 指针类型的话可以修改
    • 值类型只能作为只读的
    • 一般将指针类型作为读写的接受者即可
//定义一个integer类型
type Integer int64
func (i *Integer) Print()  {
fmt.Printf("i=%dn",*i)
}
func (i *Integer) Set(b int64) {
*i = Integer(b)
}
func main() {
var a Integer
a = 1000
fmt.Printf("a=%dn",a)
var b int64 = 500
a = Integer(b)
fmt.Printf("a=%dn",a)
a.Print()
a.Set(10000)
a.Print()
}

什么时候使用指针类型

  • 需要修改接受者中的值的时候
  • 接受者是大对象的时候,拷贝副本代价比较大
  • 一般来时,通常使用指针类型做为接受者
type Users struct {
s1 [100000000]int64
s2 [100000000]int64
s3 [100000000]int64
s4 [100000000]int64
}
func (u *Users) SetValue() {
for i :=0;i<len(u.s1);i++ {
u.s1[i] = 1
u.s2[i] = 1
u.s3[i] = 1
u.s4[i] = 1
}
}
func main() {
var u *Users = new(Users)
start := time.Now().UnixNano()
u.SetValue()
end := time.Now().UnixNano()
fmt.Printf("总耗时:%v msn",(end-start)/1000000)
}

方法的继承

  • 结构体继承
  • 方法继承
type Animal struct {
Name string
Age  int
}
func (a *Animal) SetName(name string) {
a.Name = name
}
func (a *Animal) SetAge(age int) {
a.Age = age
}
func (a *Animal) Print() {
fmt.Printf("a.name=%s a.age=%dn",a.Name,a.Age)
}
type Brids struct {
//继承父类,使用指针,初始化的时候也需要初始化父类
*Animal
}
func (b *Brids) Fly() {
fmt.Printf("name %s is flying n",b.Name)
}
func main() {
//继承父类,使用指针,初始化的时候也需要初始化父类
var b *Brids = &Brids{
&Animal{},
}
//继承了父类的方法
b.SetName("birds")
b.SetAge(12)
//调用自己的方法
b.Fly()
}

多重继承与冲突解决

  • 不推荐多重继承

结构体转成json(序列化)

type Animal struct {
Name string
Age  int
}
func (a *Animal) SetName(name string) {
a.Name = name
}
func (a *Animal) SetAge(age int) {
a.Age = age
}
func (a *Animal) Print() {
fmt.Printf("a.name=%s a.age=%dn",a.Name,a.Age)
}
type Brids struct {
//继承父类,使用指针,初始化的时候也需要初始化父类
*Animal
}
func (b *Brids) Fly() {
fmt.Printf("name %s is flying n",b.Name)
}
func main() {
//继承父类,使用指针,初始化的时候也需要初始化父类
var b *Brids = &Brids{
&Animal{},
}
//继承了父类的方法
b.SetName("birds")
b.SetAge(12)
//调用自己的方法
b.Fly()
// json序列化
data,err := json.Marshal(b)
fmt.Printf("marshal result:%s,error :%vn",data,err)
//反序列化:变成结构体
var c Brids
json.Unmarshal(data,&c)
fmt.Printf("%#vn",c.Animal)
}

spring的ioc依赖注入的三种方法(xml方式)

上一篇

SpringMVC——起步

下一篇

你也可能喜欢

评论已经被关闭。

插入图片

热门栏目

Go语言入门(六)结构体后续&指针

长按储存图像,分享给朋友