签名我们了解了一些golang的基础知识,可以明确的发现golang和c语言很是类似,那么看到这里,你可能更加震惊,这可能就是个新时代的c语言。
指针
变量是一种使用方便的占位符,用于引用计算机内存地址。
Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。
示例代码如下:
package main
import "fmt"
func main () {
var a int = 10
fmt.Printf("变量的地址: %x\n" , &a )
}
输出结果如下,可能这里不同的电脑有一些不同的输出结果:
变量的地址: c420014058
指针的概念是:指向任何一个值的内存地址,是内存地址的编号。重点:
是go中基本数据类型
代表内存地址
可以指向任意数据的地址
不同数据类型的指针需要不同的数据类型和指针符号组合来表示
我们来看看简单的一些实例:
var ip *int
var fp *float32
指针和其他类型的变量一样,我们需要申明和赋值后才能使用,看看下面的demo:
package main
import "fmt"
func main () {
var a int = 20
var aPointer *int
aPointer = &a
fmt.Printf("a 变量的地址是: %x\n" , &a)
fmt.Printf("aPointer 变量储存的指针地址: %x\n" , aPointer)
fmt.Printf("*aPointer 变量的值: %d\n" , *aPointer)
}
输出结果如下(不同电脑可能实际地址不同):
a 变量的地址是: c420014050 aPointer 变量储存的指针地址: c420014050 *aPointer 变量的值: 20
其实关于指针更加详尽的用法可以看看大学c语言教材,以及数据结构c语言版。
空指针
当一个指针被定义后没有分配到任何变量时,它的值为 nil。
nil 指针也称为空指针。
nil在概念上和其它语言的null、None、nil、NULL一样,都指代零值或空值。
一个指针变量通常缩写为 ptr。
注意,指针还有以下操作:
指针数组(核心是数组和指针)
多级指针(指向指针的指针)
函数的指针参数
我们来看看下面的例子:
package main
import "fmt"
func main () {
var a int = 20
var aPointer *int
aPointer = &a
fmt.Printf("a 变量的地址是: %x\n" , &a)
fmt.Printf("aPointer 变量储存的指针地址: %x\n" , aPointer)
fmt.Printf("*aPointer 变量的值: %d\n" , *aPointer)
b := 35
bPointer := &b
fmt.Printf("a = %d ,b = %d \n" , a, b)
fmt.Printf("aPointer = %x ,bPointer = %x \n" , aPointer, bPointer)
swap(aPointer, bPointer)
fmt.Println("交换后的结果" )
fmt.Printf("a = %d ,b = %d \n" , a, b)
fmt.Printf("aPointer = %x ,bPointer = %x \n" , aPointer, bPointer)
pBPtr := &bPointer
fmt.Printf("pBPtr = %x ,*pBPtr = %x ,**pBPtr = %x \n" , pBPtr, *pBPtr, **pBPtr)
}
func swap (a, b *int ) {
tmp := *a
*a = *b
*b = tmp
}
输出的结果是hi:
a 变量的地址是: c420014050 aPointer 变量储存的指针地址: c420014050 *aPointer 变量的值: 20 a = 20 ,b = 35 aPointer = c420014050 ,bPointer = c420014060 交换后的结果 a = 35 ,b = 20 aPointer = c420014050 ,bPointer = c420014060 pBPtr = c42000c030 ,*pBPtr = c420014060 ,**pBPtr = 14
在上面的例子中,我们可以明显的看到a、b的值在交换后发生了变化,但是aPointer和bPointer的值并没有发生变化。
在交换函数中,我们把a、b的值通过指针操作的方式直接更改了,但是aPointer和bPointer是指向了a、b的地址,我们并没有改变他们,则有aPointer和bPointer值没有变化。
接着我们申明并且初始化了一个二级指针pBPtr,他的值是bPointer这个指针变量的地址,接着*pBPtr的值是bPointer指向的地址也即是b的地址,所以**pBPtr的值是b的值。
结构体
结构体,和我们在c语言中遇到的一样,用来将不同数据(无论数据类型是否相同)组装在一起。在其他的面向对象语言中,比如说java,我们习惯来写bean对象,如下:
class Person implements Serializable {
private String name;
private Integer age;
}
那么我们在go中如何操作呢?
type Person struct {
name string
age int
}
当然,我们不妨看看具体demo:
package main
import "fmt"
type Person struct {
name string
age int
}
func (person Person) logPerson () {
fmt.Printf("%s,年龄:%d" , person.name, person.age)
}
func main () {
var aPerson Person
aPerson.name = "go语言"
aPerson.age = 8
aPerson.logPerson()
}
在上面的代码中,我们使用了一些知识点:
变量,申明和赋值
包名、导包、主函数
函数、方法
结构体
我们再主函数中,申明了aPerson变量,且数据类型是结构体Person。然后我们针对结构体的具体属性进行了初始化,然后调用结构体自身的方法实现了打印Person的相关信息。
当然结构体有一些以下操作:
属性访问,结构体变量名.属性名
类似基本数据类型的使用方法(申明变量、函数参数、指针等)
下面的demo基本阐述了结构体的常规用法:
package main
import "fmt"
type Person struct {
name string
age int
}
func (person Person) logPerson () {
fmt.Printf("%s,年龄:%d \n" , person.name, person.age)
}
func printPersonByPointer (person *Person) {
fmt.Printf("%s,年龄:%d \n" , person.name, person.age)
}
func printPerson (person Person) {
fmt.Printf("%s,年龄:%d \n" , person.name, person.age)
}
func main () {
var aPerson Person
aPerson.name = "go语言"
aPerson.age = 8
aPerson.logPerson()
printPersonByPointer(&aPerson)
printPerson(aPerson)
}
注意:在go语言中,不支持函数重载
总结
go语言和c语言又很多类似的地方。指针和结构体都是c语言中类似的概念。
指针支持任意数据类型的操作,指针申明格式为:var *name dataType
指针存储内存地址,&是取变量的地址,*是取指针指向内存的值
多级指针的层级
结构体可以称之为扩展数据类型或包装数据类型
结构体用于定义非基本数据类型
结构体的基本操作(属性读写、函数参数、结构体指针)
如果你认可我所做的事情,并且认为我做的事对你有一定的帮助,希望你也能打赏我一杯咖啡,谢谢。