发布于 2026-01-06 0 阅读
0

Go 语言 指针 语言 指针 语言 Go 语言

Go 语言 指针 语言 指针 语言 Go 语言

指针类型ที่เอาไว้เก็บ地址แต่ถ้าจะให้เข้าใจต้องถามต่อไปว่า地址กันไปทำไม

多变的

记忆记忆机器码การอ้างอิงหน่วยเก็บข้อมูลใน内存จะใช้หมายเลข地址แต่อย่างไรก็ตามภาษาคอมพิวเตอร์ที่ สร้างขึ้นมาเพื่อให้เราไม่ต้องเขียน机器码去吧地址 กันแล้ว变量 变量เนี่ยให้เราใช้ซึ่งเราก็ใช้ชื่อตัวแปร แทนที่ตำแหน่งเก็บข้อมูลเช่น



package main

import (
    "fmt"
)

func main() {
    a := 10
    b := 20
    c := a + b
    fmt.Println(c)
}


Enter fullscreen mode Exit fullscreen mode

เราก็มีที่เก็บข้อมูลชื่อ a เก็บ 10 ชื่อ b เก็บ 20 และ c เก็บผลลัพธ์ที่ได้ของ a + b คือ 30

指针指针เลยถูกมั้ยครับ变量作用域,กฎเกณฑ์ในการส่งค่าไปให้ฟังก์ชันและการ返回Go 语言 Go 语言 Go 语言 Go 语言 Go 语言ออกแบบเอาไว้ทำอะไร

范围

ตัวแปรใช้ชื่อในการอ้างอิง แต่ว่าก็มีขอบเขตในการอ้างอิงชื่อนั้นเช่นกัน范围 范围 范围 Go 范围指针作用域 作用域

函数功能和尚ฟังก์ชันอื่นๆอาจจะมีชืน่อตัวแปรเหมือกันได้ แต่ก็ถือว่าเป็นคนละตัวกันเช่น



package main

import (
    "fmt"
)

func sayHello(name string) {
    msg := "Hello " + name
    fmt.Println(msg)
}

func main() {
    var msg string
    sayHello("Por")
    fmt.Println("Main => ", msg)
}


Enter fullscreen mode Exit fullscreen mode

เมื่อรันโปรแกรมนี้จะได้



Hello Por
Main => 


Enter fullscreen mode Exit fullscreen mode

จะเห็นว่าตัวแปร msg ใน main function ไม่ใช่ตัวเดียวกันกับ msg ใน sayHello แม้จะชื่อเหมือนกันก็ตาม

函数功能

函数 参数 参数 参数เวลาเราเรียกใช้งานเราก็ต้องส่งค่าไปด้วย去吧复制品参数设置



package main

import (
    "fmt"
)

func add(a, b int) int {
    return a + b
}

func main() {
    fmt.Println(add(10, 20))
}


Enter fullscreen mode Exit fullscreen mode

เมื่อเราเรียกadd(10, 20)ตัวแปร a และ b ที่เป็น参数ของ功能添加复制 ค่า 10 และ 20 ให้ตามลำดับ

ถ้าเรียกแบบนี้



func main() {
    a := 10
    b := 20
    fmt.Println(add(a, b))
}


Enter fullscreen mode Exit fullscreen mode

ั่นคือมีตัวแปร a และ b ใน main อยู่แล้วแต่ตอเรียกadd(a, b)复制 ค่า a และ b ของ main ไปให้ a และ b ที่เป็น 参数 ของ 添加功能范围แม้ชื่อเหมือนกันแต่เป็นคนละตัว

返回值函数

返回值函数复制品功能添加功能添加功能



package main

import (
    "fmt"
)

func add(a, b int) int {
    c := a + b
    return c
}

func main() {
    a := 10
    b := 20
    c := add(a, b)
    fmt.Println(c)
}


Enter fullscreen mode Exit fullscreen mode

添加并添加 添加添加return c复制 ค่าของ c ออกไปเมื่อเรากำหนดผลลัพธ์ของadd(a, b)ให้ c ใน main function ใ็จะเกิดตัวแปร c อีกตัวที่มีscope ใน main function โดย copy ค่าที่ 返回 ได้กลับมาเก็บไว้ในตัวแปร c

去吧ในการส่งค่าและรีเทิร์น ค่ากลับมาเป็นแบบนี้เสมอ复制范围ของอีกฟังก์ชันให้กับอีกฟังก์ชัน参数 参数 返回 参数 返回值类型อะไรก็ตาม

复制品

จริงๆแล้วทุกๆการกำหนดค่าของ去复制ค่าจากที่หนึ่งไปอีกที่หนึ่งทั้งหมดเช่น



a := 10
b := a
c := b


Enter fullscreen mode Exit fullscreen mode

ก็คือ a, b และ c เป็นคนละตัวแปร และการกำหนดค่า复制品:==​ค่าจากด้านขวาไปทางด้านซ้ายทั้งหมด

复制功能 复制ด้วยเพราะมันก็คือการกำหนดค่าเห มือนกันคือกำหนดค่าให้กับตัวแปร 范围ของฟังก์ชันนั่นเอง

指针

指针指针พอเรารู้ว่าทุกอย่างในการส ่งค่าไปให้ฟังก์ชันเป็นการ复制 เสมอ功能 功能 功能เช่น



package main

import (
    "fmt"
    "strings"
)

func upperAllLetter(str string) {
    str = strings.ToUpper(str)
}

func main() {
    name := "Weerasak"
    upperAllLetter(name)
    fmt.Println(name)
}


Enter fullscreen mode Exit fullscreen mode

ซึ่งเราคาดว่าเรียกupperAllLetter(name)ค่าใน名称ต้องเปลี่ยนเป็น上部ทั้งหมดแต่ปรากฎว่าได้ ค่าเดิมเพราะเพื่อเรียก function มันคือการ复制名称主要参数str、函数str名称 ใน main

ถ้าเราอยากให้ฟังก์ชันที่เราเรีย กเปลี่ยนค่าของตัวแปรที่อยู่คนละ范围 ได้จริงๆต้องทำอย่างไร

ในGo指针โดยสิ่งที่指针เก็บคือ地址ของตัวแปรอื่นหรือตำแหน่งหน่วยความจำอื่นๆ ซึ่งก็ไม่ต่างกับตัวแปรอื่นๆ คือเกิดขึ้นมาเพื่อเก็บข้อมูล地址การได้มาซึ่งเลข 地址ใน Go ก็ไม่ใช่การกำหนดเลขมั่วๆ สิ่งที่เตรียมให้คือ操作员&ในการเอาค่า地址ออกมา (หรือใช้内置函数新地址ออกมาโดยไม่ต้องใช้ตัวแปร ซึ่งก็ไม่ค่อยได้ใช้เท่าไหร่ นานๆใช้ที)
เราไม่ได้ทำอะไรกับเลข地址???????????????????????????????????????????????????????????????????????????????????????????????????????????指针地址 操作员*

ตัวอย่างเช่น



package main

import (
    "fmt"
)

func main() {
    name := "Por"

    // ถ้าประกาศโดยใช้ data type ด้วยก็คือใช้ 
    // var pointerToName *string = &name
    pointerToName := &name 

    *pointerToName = "Weerasak"
    fmt.Println(name)
}


Enter fullscreen mode Exit fullscreen mode

指针范围 เดียวกันหรอก จะทำทำไมเล่าก็เมื่อเราก็ใช้名称 范围 范围

指针มาใช้บ่อยที่สุดคือ เอามาใช้เวลาเราต้องการให้ฟังก์ชัน แก้ไขค่าของตัวแปรอื่นที่ส่งเข้ามา เพราะในเมื่อแก้ตรงๆไม่ได้ แต่เราส่ง指针มาเราจะใช้运算符*แก้อ้อมๆ(间接)ได้นั่นเอง

ที่นี้มาเขียนฟังก์ชัน upperAllLetter参数类型指针类型指针字符串类型指针字符串类型



package main

import (
    "fmt"
    "strings"
)

func upperAllLetter(str *string) {
    *str = strings.ToUpper(*str)
}

func main() {
    name := "Weerasak"
    upperAllLetter(&name)
    fmt.Println(name)
}


Enter fullscreen mode Exit fullscreen mode

类型 参数 参数 名称เฉยๆไม่ได้แล้วเพราะมันจะผิด类型ของ参数指针指针 细绳

สิ่งที่เราทำได้ก็คือใช้操作员&เพื่อส่ง地址ของ名称ไปให้แทน

ผลการทำงานก็จะเห็นว่า name ของ main โดนเปลี่ยนไปด้วยตามที่ต้องการแล้ว โดยที่กฎเกณฑ์เรื่องการส่งค่ายังคงเดิมคือ COPY ค่าเหมือนเดิมแค่ในเคสนี้ค่าที่ถูก复制指针ที่เป็นเลข地址นั่นเอง

指针结构

Struct 类型 int、bool、string 类型 类型 类型类型 类型 类型 类型 类型 类型 类型 类型 类型 字段 结构体

字段 字段หรือเปลี่ยนค่าบาง字段ได้ผ่านทาง.(点)เช่น



package main

import (
    "fmt"
)

type Profile struct {
    Name string
    Age  int
}

func main() {
    p := Profile{
        Name: "Por",
        Age:  35,
    }
    fmt.Println(p.Name)
    fmt.Println(p.Age)

    p.Name = "Weerasak"
    fmt.Println(p.Name)
}


Enter fullscreen mode Exit fullscreen mode

功能 功能 เพื่อแก้ไขค่าของ struct 结构体 函数 结构体



package main

import (
    "fmt"
    "strings"
)

type Profile struct {
    Name string
    Age  int
}

func upperProfileName(p Profile) {
    p.Name = strings.ToUpper(p.Name)
}

func main() {
    p := Profile{
        Name: "Por",
        Age:  35,
    }
    upperProfileName(p)
    fmt.Println(p.Name)
}


Enter fullscreen mode Exit fullscreen mode

เวลาเราส่ง p ไป ก็คือการ 复制 p ให้กับ p复制 复制 字段 字段名称 名称 功能名称 名称 功能 主要功能

指针ช่วยได้เหมือนเดิมโดยเปลี่ยนโค้ดเป็แบบนี้



package main

import (
    "fmt"
    "strings"
)

type Profile struct {
    Name string
    Age  int
}

func upperProfileName(p *Profile) {
    p.Name = strings.ToUpper(p.Name)
}

func main() {
    p := Profile{
        Name: "Por",
        Age:  35,
    }
    upperProfileName(&p)
    fmt.Println(p.Name)
}


Enter fullscreen mode Exit fullscreen mode

指针 struct struct struct struct คือเราสามารถใช้.点 ได้เลย ไม่ต้องใช้ 运算符*ในการแก้ไขค่าของ 字段 ผ่านทาง 指针เราจะใช้*struct struct 结构体ซึ่งก็ไม่บ่อยที่จะทำแบบนั้น

切片地图

切片 และ 地图 ของ Go จะพิเศษจากตัวแปรธรรมดาหน่อยเพรา ะมันถูกออกแบบมาให้เก็บข้อมูลแบบ动态大小 附加元素 切片หรือเอาออกก็ได้สำหรับ地图ก็เพิ่ม键值หรือลบออกก็ได้เช่นกัน

การจัดการภายในของ切片และ地图คือจะมีการเก็บ地址แบบ指针ั่นแหละของ元素เอาไว้ตัว切片นและ地图ไม่ใช่ก้อ元素เองโดยตรง

参数、切片、地图、复制เหมือนเดิมกับเหมือนตัวแปรอื่น类型 ใน Go复制 复制

切片、映射、复制、指针、复制地址复制元素 复制元素元素元素参数 切片 映射 映射 切片 映射ของฝั่งที่เรียกใช้ด้วยนั่นเองเช่น



package main

import (
    "fmt"
)

func doubleAllElement(nums []int) {
    for i := range nums {
        nums[i] *= 2
    }
}

func main() {
    nums := []int{1, 2, 3}
    doubleAllElement(nums)
    fmt.Println(nums)
}


Enter fullscreen mode Exit fullscreen mode

复制doubleAllElements(nums)nums 和 main 复制 nums 和 doubleAllElements แต่ว่าสิ่งที่复制ไปคือ地址ของ元素ด้วย元素 元素 doubleAllElements ก็จะกระทบกับelementของnumsในmainด้วย

乌鲁木齐地图 乌鲁木齐地图



package main

import (
    "fmt"
)

func doubleAllElement(nums map[string]int) {
    for key := range nums {
        nums[key] *= 2
    }
}

func main() {
    nums := map[string]int{
        "one":   1,
        "two":   2,
        "three": 3,
    }
    doubleAllElement(nums)
    fmt.Println(nums)
}


Enter fullscreen mode Exit fullscreen mode

复制 复制 复制地址 元素 元素 元素 元素 元素 元素

แต่ถ้าเราอยากให้เกิดการเปลี่ ยนแปลงกับตัวแปรทั้งก้อนจริงๆ指针类型 指针类型 指针类型解组功能JSON格式去吧指针เสมอแม้ว่าตัวแปรจะเป็น切片หรือ地图ก็ตามเพื่อจะได้เปลี่ยนแปลงข้ อมูลทั้งก้อนของตัวแปรได้ผ่าน指针 เช่นถ้าทำแบบนี้



package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    jsonText := []byte(`[1, 2, 3]`)
    var nums []int
    json.Unmarshal(jsonText, nums) 
    // ที่ถูกต้องเป็นแบบนี้ json.Unmarshal(jsonText, &nums)
    fmt.Println(nums)
}


Enter fullscreen mode Exit fullscreen mode

ตัวแปร nums จะไม่ได้ค่า[1, 2, 3]แน่นอน ที่ถูกต้องคือต้องเรียกjson.Unmarshal(jsonText, &nums)ส่ง地址(指针ของ切片[]int) ไปให้แทน

返回指针

函数功能เพื่อฟังก์ชันทำงานจบ重复使用 重复使用 重复使用返回复制เช่นกันตัวแปรเกิดใหม่ที่อ ีกฟังก์ชันที่เอามาเก็บค่า ก็ถือเป็นคนละตัวกัน

แต่บางครั้งเราต้องการสร ้างฟังก์ชันที่ทำหน้าที่安装程序设置设置ซับซ้อนแล้วต้องใช้หลายๆที่ เราก็ต้องการแยกเป็功能返回复制 复制 复制

指针 指针 指针返回数据 返回地址 返回地址指针指针函数功能类型 struct struct



package main

import (
"fmt"
)

type App struct {
db DB
conf Config
}

func NewApp() (*App, error) {
db, err := NewDB()
if err != nil {
return nil, err
}
conf, err := NewConf()
if err != nil {
return nil, err
}

<span class="k">return</span> <span class="o">&amp;</span><span class="n">App</span> <span class="p">{</span>
    <span class="n">db</span><span class="o">:</span> <span class="n">db</span><span class="p">,</span>
    <span class="n">conf</span><span class="o">:</span> <span class="n">conf</span><span class="p">,</span>
<span class="p">},</span> <span class="no">nil</span>
Enter fullscreen mode Exit fullscreen mode

}

func main() {
app, err := NewApp()
if err != nil {
panic(err)
}
app.Run()
}

Enter fullscreen mode Exit fullscreen mode




สรุป

去吧 去吧 การกำหนดค่าให้ตัวแปร功能 ทุกอย่างคือการ 复制ค่าเสมอ

函数功能指针类型 运算符*指针เก็บเอาไว้อยู่นั่นเอง

请我喝杯咖啡

文章来源:https://dev.to/iporsut/go-pointer-pointer-go-3212