>  기사  >  백엔드 개발  >  예시를 통해 Go 구조체 인스턴스화 및 할당 설명

예시를 통해 Go 구조체 인스턴스화 및 할당 설명

藏色散人
藏色散人앞으로
2021-11-19 16:19:372906검색
Golangt의 Structs의 다양한 인스턴스 및 할당 방법은 잠시 전송되고 포인터는 잠시 혼란스러워지기 때문에 전체를 정리하고 이해하기로 결정했습니다.

먼저 구조를 정의하고 아래에서 코드와 함께 설명해보세요.

package mainimport "fmt"type Person struct {
    Name string
    Age int
    Descprtion string}

예제 1

p는 가장 일반적인 방식으로 구조체를 인스턴스화하고 변수 p는 Person 구조체를 가져옵니다.
p := Person{}
p.Name = "小明"

fmt.Printf("p:%+v 变量地址:%p\n", p, &p)
fmt.Println("===========")

// result:
// p:{Name:小明 Age:0 Descprtion:} 变量地址:0xc000078480
// ===========

예제 2

변수 p1은 p에 의해 할당됩니다. Golang 언어는 값 전송이므로 할당 후 p1의 수정은 p에 영향을 미치지 않습니다. Golang의 할당에는 PHP 변수 할당과 같은 쓰기 시 복사(쓰기 시 복사) 메커니즘이 없다는 것도 출력에서 ​​볼 수 있습니다.

p1 := p
fmt.Printf("p1:%+v 变量地址:%p\n", p1, &p1) // 不存在写时复制
p1.Name = "小明p1"
fmt.Printf("p:%+v 变量地址:%p\n", p, &p)
fmt.Printf("p1:%+v 变量地址:%p\n", p1, &p1)
fmt.Println("===========")

// result:
// p1:{Name:小明 Age:0 Descprtion:} 变量地址:0xc0000784e0
// p:{Name:小明 Age:0 Descprtion:} 变量地址:0xc000078480
// p1:{Name:小明p1 Age:0 Descprtion:} 变量地址:0xc0000784e0
// ===========

예 3值传递,赋值后,对 p1 的修改并不会影响到 p;

从第一个输出也可以看得出,Golang 的赋值并不存在像PHP变量赋值时的写时复制(copy on write)机制。

p2 := &p // 等同于 var p2 *Person = &p
fmt.Printf("p2:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p2, p2, &p2)
p2.Name = "小明p2"
fmt.Printf("p1:%+v 变量地址:%p\n", p, &p)
fmt.Printf("p2:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p2, p2, &p2)
fmt.Println("===========")

// result:
// p2:&{Name:小明 Age:0 Descprtion:} 指针变量指向地址(变量值):0xc000078480 变量地址:0xc000006030
// p1:{Name:小明p2 Age:0 Descprtion:} 变量地址:0xc000078480
// p2:&{Name:小明p2 Age:0 Descprtion:} 指针变量指向地址(变量值):0xc000078480 变量地址:0xc000006030
// ===========

实例三

利用取地址符将 p 的地址赋值给 p2,变量 p2 是一个指针,存放着指向 p 的地址。当 p2 修改了结构体中元素 Name 时,通过 p 访问结构体对应的值也相应地发生了变化。

p3 := new(Person)
fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
p3.Age = 3 // 等同于 (*p3).Age = 3
fmt.Println("================ 操作 Age ================")
fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
*p3 = Person{
    Name: "小明p3",
}
fmt.Println("================ 操作 Name ================")
fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
p5 := p3
fmt.Println("================ p5 := p3 ================")
fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
fmt.Printf("p5:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p5, p5, &p5)
p3.Name = "小明p3修改"
fmt.Println("================ p3 修改 ================")
fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
fmt.Printf("p5:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p5, p5, &p5)
fmt.Println("===========")

// result:
// p3:&{Name: Age:0 Descprtion:} 指针变量指向地址(变量值):0xc000078630 变量地址:0xc000006038
// ================ 操作 Age ================
// p3:&{Name: Age:3 Descprtion:} 指针变量指向地址(变量值):0xc000078630 变量地址:0xc000006038
// ================ 操作 Name ================
// p3:&{Name:小明p3 Age:0 Descprtion:} 指针变量指向地址(变量值):0xc000078630 变量地址:0xc000006038
// ================ p5 := p3 ================
// p5:&{Name:小明p3 Age:0 Descprtion:} 指针变量指向地址(变量值):0xc000078630 变量地址:0xc000006040
// ================ p3 修改 ================
// p3:&{Name:小明p3修改 Age:0 Descprtion:} 指针变量指向地址(变量值):0xc000078630 变量地址:0xc000006038
// p5:&{Name:小明p3修改 Age:0 Descprtion:} 指针变量指向地址(变量值):0xc000078630 变量地址:0xc000006040
// ===========

实例四

变量 p3 由 new(Person) 得来。new 将开辟一块内存,返回内存地址给 p3,也即 p3 是一个指向这块内存的指针。

p3 是指向结构体的指针,它有两种方式可以操作结构体,p3.Age = 3*p3 = Person{Name: "小明p3"}

주소 문자 사용 p의 주소를 p2에 할당합니다. 변수 p2는 p를 가리키는 주소를 저장하는 포인터입니다. p2가 구조의 Name 요소를 수정하면 p를 통해 액세스되는 구조에 해당하는 값도 그에 따라 변경됩니다.

p4 := &Person{
    Name: "小明p4",}fmt.Printf("%+v %p\n", p4, &p4)// result:// &{Name:小明p4 Age:0 Descprtion:} 0xc000006048
예 4

new의 변수 p3 (사람) 알겠습니다. new는 메모리 조각을 열고 메모리 주소를 p3에 반환합니다. 즉, p3은 이 메모리에 대한 포인터입니다.

p3은 구조에 대한 포인터입니다. 구조를 작동하는 방법에는 p3.Age = 3*p3 = Person{Name: "Xiao Ming p3"}이 있습니다. code>에서 두 번째 방법 이후에 연산을 수행하면 첫 번째 방법에서 수정된 구조를 덮어쓰게 됩니다.

p3은 포인터이므로 p3이 p5에 할당되면 p5도 이 메모리 주소를 가리킵니다.

package mainimport "fmt"type Person struct {
    Name string
    Age int
    Descprtion string}func main() {
    p := Person{}
    p.Name = "小明"

    fmt.Printf("p:%+v 变量地址:%p\n", p, &p)
    fmt.Println("===========")

    p1 := p
    fmt.Printf("p1:%+v 变量地址:%p\n", p1, &p1) // 不存在写时复制
    p1.Name = "小明p1"
    fmt.Printf("p:%+v 变量地址:%p\n", p, &p)
    fmt.Printf("p1:%+v 变量地址:%p\n", p1, &p1)
    fmt.Println("===========")

    p2 := &p
    fmt.Printf("p2:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p2, p2, &p2)
    p2.Name = "小明p2"
    fmt.Printf("p1:%+v 变量地址:%p\n", p, &p)
    fmt.Printf("p2:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p2, p2, &p2)
    fmt.Println("===========")

    p3 := new(Person)
    fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
    p3.Age = 3 // 等同于 (*p3).Age = 3
    fmt.Println("================ 操作 Age ================")
    fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
    *p3 = Person{
        Name: "小明p3",
    }
    fmt.Println("================ 操作 Name ================")
    fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
    p5 := p3
    fmt.Println("================ p5 := p3 ================")
    fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
    fmt.Printf("p5:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p5, p5, &p5)
    p3.Name = "小明p3修改"
    fmt.Println("================ p3 修改 ================")
    fmt.Printf("p3:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p3, p3, &p3)
    fmt.Printf("p5:%+v 指针变量指向地址(变量值):%p 变量地址:%p\n", p5, p5, &p5)
    fmt.Println("===========")

    p4 := &Person{
        Name: "小明p4",
    }
    fmt.Printf("%+v %p\n", p4, &p4)}

예제 5

🎜 p4의 인스턴스화 방법도 포인터를 얻습니다. 이 인스턴스화 방법은 p3의 인스턴스화와 동일하지만 p4의 쓰기 방법이 더 일반적으로 사용됩니다. 🎜🎜🎜🎜rrreee🎜첨부된 코드는 전체 코드입니다: 🎜rrreee🎜End! 🎜

위 내용은 예시를 통해 Go 구조체 인스턴스화 및 할당 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 learnku.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제