签名我们了解了一些 golang 的基础知识,可以明确的发现 golang 和 c 语言很是类似,那么看到这里,你可能更加震惊,这可能就是个新时代的 c 语言。
指针
变量是一种使用方便的占位符,用于引用计算机内存地址。 Go 语言的取地址符是 &,放到一个变量前使用就会返回相应变量的内存地址。
示例代码如下:
- package main
- import "fmt"
- func main() {
- var a int = 10
- fmt.Printf("变量的地址: %x\n", &a)
- }
输出结果如下,可能这里不同的电脑有一些不同的输出结果:
- 变量的地址: c420014058
指针的概念是:指向任何一个值的内存地址,是内存地址的编号。重点:
我们来看看简单的一些实例:
- //指针申明格式
- // var var_name *var-type
- // var-type 为指针类型,var_name 为指针变量名,* 号用于指定变量是作为一个指针。
- 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 对象,如下:
- //在java中创建Person实体
- 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
- }
- //这里是方法,输入Person的方法
- 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 语言中类似的概念。
如果你认可我所做的事情,并且认为我做的事对你有一定的帮助,希望你也能打赏我一杯咖啡,谢谢。
来源: https://juejin.im/post/5a3cbc4ef265da431b6d646e