😋 大家好,我是YAy_17,是一枚爱好网安的小白。
本人水平有限,欢迎各位师傅指点,欢迎关注 😁,一起学习 💗 ,一起进步 ⭐ 。
⭐ 此后如竟没有炬火,我便是唯一的光。 ⭐Go语言中的指针
Go语言中的函数传参都是值传递,当我们想要修改某个变量的时候,我们可以创建一个指向该变量地址的指针变量,传递数据使用指针,而无需拷贝数据。
类型指针不能进行偏移和运算。
Go语言中的指针操作非常简单,只需要记住两个符号&(取地址)和*(根据地址取值)
指针地址和指针类型
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&字符放在变量前面对变量进行取地址操作。Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型,如: *int、 *int64、*string等。
指针的语法
一个指针变量指向了一个值的内存地址。(也就是我们声明了一个指针之后,可以像变量赋值一样,把一个值的内存地址放入到指针当中。)类似于变量和常量,在使用指针前你需要声明指针。指针声明格式如下:
var var _name *var_type
var_type :为指针类型 var_name :为指针变量名 *:用于指定变量是作为一个指针。
package main
import "fmt"
func main() {
    var p *int
    fmt.Printf("p: %v\n", p)
    fmt.Printf("p: %T\n", p)
    var a int = 100
    p = &a
    fmt.Printf("p: %v\n", *p)
    var str *string
    fmt.Printf("str: %v\n", str)
    fmt.Printf("str: %T\n", str)
    s := "Y4y17"
    str = &s
    fmt.Printf("str: %v\n", *str)
    var bl *bool
    fmt.Printf("bl: %v\n", bl)
    fmt.Printf("bl: %T\n", bl)
    var b bool = true
    bl = &b
    fmt.Printf("bl: %v\n", *bl)
}输出结果为:
 
   指向数组的指针
定义语法
var ptr [MAX]*int //表示数组里面的元素的类型是指针类型
package main
import "fmt"
func main() {
    a := [3]int{1, 2, 3}
    var p [3]*int
    fmt.Printf("p: %v\n", p)
    for i := 0; i < len(a); i++ {
        p[i] = &a[i]
        fmt.Printf("p[i]: %v\n", *p[i])
    }
}输出结果为:
 
   Go语言中的类型定义和类型别名
Go语言类型定义
type Newtype Type
package main
import "fmt"
func main() {
    type Myint int
    var i Myint = 100
    fmt.Printf("i: %T,%v\n", i, i)
}输出结果如下:
i: main.Myint,100Go语言类型别名
type Newtype=Typepackage main
import "fmt"
func main() {
	type Myint = int
    var i Myint = 100
    fmt.Printf("i: %T,%v\n", i, i)
}
i: int,100Go语言中的类型定义和类型别名的区别
- 类型定义相当于定义了一个全新的类型,与之前的类型不同;但是类型别名并没有定义一个新的类型,而是使用一个别名来替换之前的类型 
- 类型别名只会在代码中存在,在编译完成之后并不会存在该别名 
- 因为类型别名和原来的类型是一致的,所以原来类型所拥有的方法,类型别名中也可以调用,但是如果是重新定义的一个类型,那么不可以调用之前的任何方法 
Go语言中的结构体
在使用结构体之前我们需要定义一个结构体类型,之后通过定义的这个结构体类型在去定义结构体变量;语法结构如下:
type struct_variable_type struct{
member definition;
member definition;
......
member definition;
}	type:结构体定义关键字
struct_variable_type:结构体类型名称
member definition:成员定义
package main
import "fmt"
func main() {
    type person struct {
        name string
        age  int
        sex  string
    }
    var tom person
    fmt.Printf("tom: %v\n", tom)
    tom.name = "tom"
    tom.sex = "man"
    tom.age = 20
    fmt.Printf("tom: %v\n", tom)
    fmt.Printf("tom.name: %v\n", tom.name)
}输出的结果如下:
 
   匿名结构体
package main
import "fmt"
func main() {
    var tom struct {	//匿名结构体在定义的时候不再使用type 而是var
        name string
        age  int
        sex  string
    }
    tom.name = "tom"
    tom.sex = "man"
    tom.age = 20
    fmt.Printf("tom: %v\n", tom)
    fmt.Printf("tom.name: %v\n", tom.name)
}结构体的初始化
package main
import "fmt"
func main() {
    type person struct {
        name, email string
        age, id     int
    }
    //第一种初始化的方法:键值对的方式
    var tom person
    tom = person{
        name:  "tom",
        email: "tom@gmail.com",
        age:   20,
        id:    111,
    }
    fmt.Printf("tom: %v\n", tom)
    //第二种初始化的方法:列表的方式
    var Y4y17 person
    Y4y17 = person{
        //这种初始化的方法,必须按照结构体成员定义的顺序进行初始化
        "Y4y17",
        "Y4y17@gmail.com",
        20,
        16,
    }
    fmt.Printf("Y4y17: %v\n", Y4y17)
    //第三种初始化的方法:支持短变量赋值
    Mary := person{
        //部分赋值也是可以的
        name: "Mary",
        id:   22,
    }
    fmt.Printf("Mary: %v\n", Mary)
}
输出结果如下:
tom: {tom tom@gmail.com 20 111}
Y4y17: {Y4y17 Y4y17@gmail.com 20 16}
Mary: {Mary  0 22}结构体指针
package main
import (
    "fmt"
)
//普通的指针变量
func test1() {
    var name string = "Y4y17"
    var nm *string
    nm = &name
    fmt.Printf("name: %v\n", name)
    fmt.Printf("nm: %v\n", nm)
    fmt.Printf("nm: %v\n", *nm)
}
//结构体指针
func test2() {
    type person struct {
        name string
        age  int
        id   int
    }
    var p_struct *person
    //这里存在3种赋值的方式
    //第一种方式:
    p_struct = &person{
        name: "Y4y17",
        age:  20,
        id:   17,
    }
    fmt.Printf("p_struct: %v\n", *p_struct)
    //第二种方式
    var tom person = person{"tom", 20, 17}
    var p_struct1 *person
    p_struct1 = &tom
    fmt.Printf("p_struct1: %v\n", *p_struct1)
    //第三种方式:
    var p_struct2 = new(person)
    p_struct2.age = 22
    p_struct2.name = "Mary"
    fmt.Printf("p_struct2: %v\n", *p_struct2)
}
func main() {
    test2()
}
输出结构如下:
p_struct: {Y4y17 20 17}
p_struct1: {tom 20 17}
p_struct2: {Mary 22 0}结构体作为函数的参数
package main
import "fmt"
type person struct {
    name string
    age  int
    id   int
}
func show_person(per person) {
    per.name = "Y4y17"
    per.age = 24
    per.id = 17
    fmt.Printf("per: %v\n", per)
}
func main() {
    Mary := person{
        name: "Mary",
        age:  23,
        id:   99,
    }
    fmt.Printf("Mary: %v\n", Mary)
    fmt.Printf("--------------------------\n")
    show_person(Mary)
    fmt.Printf("Mary: %v\n", Mary)
}
Mary: {Mary 23 99}
--------------------------
per: {Y4y17 24 17}
Mary: {Mary 23 99}package main
import "fmt"
type person struct {
    name string
    age  int
    id   int
}
func show_person(per *person) {
    per.name = "Y4y17"
    per.age = 24
    per.id = 17
    fmt.Printf("per: %v\n", *per)
}
func main() {
    Mary := person{
        name: "Mary",
        age:  23,
        id:   99,
    }
    fmt.Printf("Mary: %v\n", Mary)
    fmt.Printf("--------------------------\n")
    show_person(&Mary)
    fmt.Printf("Mary: %v\n", Mary)
}修改一下代码,使得变成传递地址的方式:
Mary: {Mary 23 99}
--------------------------
per: {Y4y17 24 17}
Mary: {Y4y17 24 17}结构体的嵌套
package main
import "fmt"
type person struct {
    name string
    age  int
    id   int
    cat  cat	//结构体中嵌套着一个cat结构体
}
type cat struct {
    name  string
    age   int
    color string
}
func main() {
    cat := cat{
        name:  "敢敢",
        age:   1,
        color: "grey",
    }
    Y4y17 := person{
        name: "Y4y17",
        age:  23,
        id:   17,
        cat:  cat,
    }
    fmt.Printf("Y4y17: %v\n", Y4y17)
    fmt.Printf("Y4y17.cat.name: %v\n", Y4y17.cat.name)
}
Y4y17: {Y4y17 23 17 {敢敢 1 grey}}
Y4y17.cat.name: 敢敢Go语言中的方法
go语言没有面向对象的特性,也没有类对象的概念。但是,可以使用结构体来模拟这些特性,我们都知道面向;象里面有类方法等概念。我们也可以声明一些方法,属于某个结构体。
Go语言方法的语法
Go中的方法,是一种特殊的函数,定义于struct之上(与struct关联、绑定),被称为struct的接受者(receiver)。通俗的讲,方法就是有接收者的函数。
语法格式如下:
type mytype struct{}
func (recv mytype) my_method( para) return_type {}
func (recv *mytype) my_method(para) return_type {}
mytype :定义一个结构体
recv∶接受该方法的结构体(receiver)my_method:方法名称
para :参数列表
return_type :返回值类型从语法格式可以看出,一个方法和一个函数非常相似,多了一个接受类型。
package main
import "fmt"
type person struct {
	name string
}
func (per person) eat() {
	fmt.Printf("%v eating...\n", per.name)
}
func (per person) sleep() {
	fmt.Printf("%v sleeping...\n", per.name)
}
func main() {
	var tom person
	tom.name = "tom"
	tom.eat()
	tom.sleep()
}
package main
import "fmt"
type customer struct {
    name string
}
func (cus customer) login(name string, pwd string) bool {
    if name == "tom" && pwd == "123" {
        return true
    } else {
        return false
    }
}
func main() {
    cus := customer{
        name: "tom",
    }
    b := cus.login("tom", "123")
    fmt.Printf("b: %v\n", b)
}Go语言方法的注意事项
- 方法的receiver type并非一定要是struct类型,type定义的类型别名、slice、map、channel、func类型等都可以。 
- struct结合它的方法就等价于面向对象中的类。只不过struct可以和它的方法分开,并非一定要属于同一个文件,但必须属于同一个包。 
- 方法有两种接收类型: (T Type)和(T *Type),它们之间有区别。 
- 方法就是函数,所以Go中没有方法重载(overload)的说法,也就是说同一个类型中的所有方法名必须都唯一。如果receiver是一个指针类型,则会自动解除引用。 
- 方法和type是分开的,意味着实例的行为(behavior)和数据存储(field)是分开的,但是它们通过receiver建立起关联关系。 
Go语言方法接收者类型
分为值类型和指针类型
package main
import "fmt"
type customer struct {
    name string
}
//传值
func (cus customer) test1() {
    cus.name = "Y4y17"
}
//传递指针
func (cus *customer) test2() {
    cus.name = "Y4y17"
}
func main() {
    cus := customer{
        name: "tom",
    }
    cus.test1()
    fmt.Printf("cus: %v\n", cus)	//cus: {tom}
    cus.test2()
    fmt.Printf("cus: %v\n", cus)	//cus: {Y4y17}
}

















![[计算机网络(第八版)]第二章 物理层(章节测试/章节作业)](https://img-blog.csdnimg.cn/0435436cab2240f59dee2cdef567ad8e.png)
