网站访客qq获取系统 报价,客户管理系统入口,湖南长沙装修公司,网页和网站的概念目录
概述
一、基本概念
指针类型#xff08;Pointer type#xff09;
非引用类型#xff08;值类型#xff09;
引用类型#xff08;Reference Types#xff09;
解引用#xff08;dereference#xff09;
二、引用类型和非引用类型的区别
三、golang数据类型…目录
概述
一、基本概念
指针类型Pointer type
非引用类型值类型
引用类型Reference Types
解引用dereference
二、引用类型和非引用类型的区别
三、golang数据类型系统里的引用类型和非引用类型
值类型Value Types
引用类型Reference Types
四、golang数据类型系统里的零值
五、Methods and pointer indirection
情况1函数的形参是值类型实参是值类型的处理情况
情况2函数的形参是值类型实参是指针类型的处理情况
情况3函数的形参是指针类型实参是值类型的处理情况
情况4函数的形参是指针类型实参是指针类型的处理情况
情况5方法的接收者是值类型方法的调用者是值类型的处理情况
情况6方法的接收者是值类型方法的调用者是指针类型的处理情况
情况7方法的调用者是指针类型方法的调用者是值类型的处理情况
情况8方法的调用者是指针类型方法的调用者是指针的处理情况
总结 概述 本文主要介绍引用类型和非引用类型的基本概念golang的数据类型系统里有哪些是引用类型和非引用类型以及引用类型和非引用的区别他们的优缺点尤其重点介绍了golang的“Methods and pointer indirection”的含义指针类型和值类型在函数参数传递和方法调用方面的区别。
一、基本概念 编程语言中引用类型和非引用类型有时也被称为值类型是两种主要的数据类型分类方式它们主要区别在于数据在内存中的存储和传递方式。
指针类型Pointer type 指针类型是指能够存储变量地址的数据类型。在 Go 中使用 *T 表示指向 T 类型的指针其中 T 是任意类型。指针类型允许我们直接操作变量的内存地址可以用来传递变量的引用以及在需要时间接访问变量的值。例如*int 表示指向整数类型的指针。
非引用类型值类型 非引用类型也称为值类型在创建变量时会在内存中分配一个新的存储空间来存储该变量的值。每个值类型的变量都有自己独立的存储空间并且变量的值会被直接复制。当你将一个值类型的变量赋值给另一个变量时实际上是创建了这个值的一个副本。对副本所做的任何修改都不会影响原始变量。因此值类型的变量在函数参数传递时也是按值传递的。在Go语言中基本数据类型如int、float64、bool、string等和数组都是值类型。
引用类型Reference Types 引用类型在创建变量时并不会在内存中直接存储数据本身而是存储一个指向数据的引用或指针。这个引用是一个地址指向在堆内存中存储的实际数据。多个引用类型的变量可以指向同一个数据。当你将一个引用类型的变量赋值给另一个变量时你其实是在复制这个引用而不是数据本身。因此所有指向同一个数据的引用类型变量都会共享这个数据
解引用dereference 解引用是指通过指针获取其所指向的值。换句话说解引用是一种操作允许我们通过指针变量访问和修改变量或对象的值。通过使用*操作符我们可以对指针变量进行解引用操作获取其所指向的值。 解引用不仅适用于基础数据类型也适用于结构体等复合类型。例如我们可以解引用一个指向结构体的指针以访问或修改结构体的字段。
需要注意的是golang对未初始化的引用类型进行解引用操作会引发运行时错误panic。这是因为未初始化的引用类型变量在内存中没有有效的值或地址尝试解引用这样的变量将导致未定义的行为
二、引用类型和非引用类型的区别 三、golang数据类型系统里的引用类型和非引用类型 在 Go 语言中类型可以分为值类型和引用类型。这两种类型的主要区别在于它们在内存中的存储方式和赋值操作的行为
值类型Value Types
值类型包括 基本数据类型如 int、float64、bool、string、complex64、complex128、rune即 int32 的别名用于表示 Unicode 码点等。 数组数组是固定长度的序列每个元素都是相同类型的值。例如 [5]int。 结构体结构体是由一组字段组成的值类型。字段可以具有不同的类型。 对于值类型的变量赋值操作会创建该值的副本。这意味着如果你修改了一个值类型变量的值它不会影响其他使用该类型值的变量。
引用类型Reference Types
引用类型包括 切片切片是对数组的抽象它提供了动态长度的、灵活且可变的序列。切片底层引用了数组的一部分或全部但它本身是一个独立的类型。 映射映射是键值对的集合。Go 语言中的映射类型使用 map 关键字定义例如 map[string]int。 通道通道用于在 Go 语言的并发程序中传递数据。它们用于实现协程之间的通信。 接口接口定义了一组方法的集合任何实现这些方法的具体类型都被认为实现了该接口。接口本身不存储数据但可以作为引用类型传递。 函数在 Go 语言中函数也可以被视为值可以赋值给变量也可以作为参数传递给其他函数。尽管函数在内存中的表示与常规的值类型略有不同但在许多上下文中它们的行为类似于引用类型。 四、golang数据类型系统里的零值 在 Go 语言中当声明一个变量但未对其进行赋值时该变量会被赋予其对应类型的零值。零值是指变量在未被显式赋值时的默认值。下面是 Go 语言中常见类型的零值 五、Methods and pointer indirection 前面的铺垫其实我们为了更好地理解“Methods and pointer indirection”。什么是“Methods and pointer indirection” functions with a pointer argument must take a pointerwhile methods with pointer receivers take either a value or a pointer as the receiver when they are called 为了更好地理解上面这段话我将问题进行了拓展即值类型和引用类型在函数传递和方法调用的不同情况下golang编译器的处理方式分别从参数传递机制拷贝机制是否更改原值方面将问题拆分了8种以下情况并用简单的代码示例来探究解释。
情况1函数的形参是值类型实参是值类型的处理情况
package mainimport fmtfunc modifyValue(val int) {val 100
}func main() {x : 10modifyValue(x)fmt.Println(x) // Output: 10 (原始值未被修改)
} 参数传递机制当函数形参是值类型实参也是值类型时编译器在函数调用时会复制实参的副本传递给函数编译器会在栈上分配内存空间将参数的值复制到栈上的内存位置然后将栈的内存地址传递给函数是否修改原始值不会修改原始值因为修改只影响参数的副本 情况2函数的形参是值类型实参是指针类型的处理情况
package mainimport fmtfunc modifyValue(val int) {val 100
}func main() {x : 10modifyValue(x)fmt.Println(x) // cannot use x (value of type *int) as int value in argument to modifyValue
} 函数的形参是值类型传递给函数逇也必须是值类型类型匹配原则 类型不匹配编译报错 情况3函数的形参是指针类型实参是值类型的处理情况
package mainimport fmtfunc modifyValue(val *int) {*val 100
}func main() {x : 10modifyValue(x)fmt.Println(x) // cannot use x (variable of type int) as *int value in argument to modifyValue
} 函数的形参是指针类型传递给函数的也必须是指针类型类型匹配原则 类型不匹配编译报错 情况4函数的形参是指针类型实参是指针类型的处理情况
package mainimport fmtfunc modifyValue(val *int) {*val 100
}func main() {x : 10modifyValue(x)fmt.Println(x) // output 100 更改原值
} 参数传递机制当函数形参是指针类型时实参也是指针类型时编译器在函数调用时会复制实参的地址传递给函数编译器会在栈上分配空间将参数的地址复制到栈的内存位置然后将栈的内存地址传递给函数是否修改原始值通过指针可以间接地修改原始值 情况5方法的接收者是值类型方法的调用者是值类型的处理情况
package mainimport fmttype Myint intfunc (m Myint) modify() {m 10
}func main() {x : Myint(5)x.modify()fmt.Println(x) //output 5
} 参数传递机制在栈上为调用者分配内存空间调用方法时会将调用者的值复制一份传递给方法的接收者。是否修改原始值不会修改原始值因为修改的只是调用者的副本 情况6方法的接收者是值类型方法的调用者是指针类型的处理情况
package mainimport fmttype Myint intfunc (m Myint) modify() {m 10
}func main() {x : Myint(5)(x).modify()fmt.Println(x) //output 5
} 参数传递机制编译器会将调用者指针解引用为值然后在解引用后的对象上调用方法在栈上分配内存空间并将指针解引用后的值复制到分配的内存位置。编译器将指针解引用然后解引用后的对象上调用方法是否修改原始值不会修改原始值因为调用者是指针类型接收者是值类型调用者后的对象是调用者的副本。 情况7方法的调用者是指针类型方法的调用者是值类型的处理情况
package mainimport fmttype Myint intfunc (m *Myint) modify() {*m 10
}func main() {x : Myint(5)x.modify()fmt.Println(x) //output 10
} 参数传递机制调用方法时编译器会隐式地取调用者的地址传递给方法的接收者是否修改原始值调用地址的副本间接修改原始值 情况8方法的调用者是指针类型方法的调用者是指针的处理情况
package mainimport fmttype Myint intfunc (m *Myint) modify() {*m 10
}func main() {x : Myint(5)(x).modify()fmt.Println(x) //output 10
}参数传递机制调用方法时直接将调用者的地址传递给方法的接收者是否修改原始值直接修改原始值 总结 对于函数的形参和实参参数的类型必须匹配。如果函数的形参是值类型则传递给它的实参必须是值类型如果形参是指针类型则传递给它的实参必须是指针类型。 而对于方法的接收者和调用者Go 允许方法的接收者是值类型这意味着可以直接使用值类型的实例调用该方法也可以是指针类型这意味着可以使用指针类型的实例调用该方法。
这种灵活性使得在设计和使用方法时更加方便可以根据具体的需求和场景选择适合的方法接收者类型。 对于函数即不附属于任何类型的函数如果函数的参数是指针类型那么调用该函数时必须传递一个指针作为参数。这是因为函数是独立存在的没有与之关联的接收者对象因此无法通过隐式的方法接收者来自动解引用指针。对于方法即附属于某个类型的函数如果方法的接收者是指针类型那么在调用该方法时可以选择传递一个值类型的接收者或者一个指针类型的接收者。如果传递的是值类型的接收者Go 语言会在内部将其自动解引用为指针类型。这是因为方法是与类型相关联的可以通过类型的值或指针来调用方法而不需要显式地进行解引用。 简而言之函数需要显式地传递指针作为参数而方法可以接受值类型或指针类型的接收者并在需要时进行自动解引用。这就是“Methods and pointer indirection”的含义所在