跳转到主要内容

标签(标签)

资源精选(342) Go开发(108) Go语言(103) Go(99) angular(82) LLM(75) 大语言模型(63) 人工智能(53) 前端开发(50) LangChain(43) golang(43) 机器学习(39) Go工程师(38) Go程序员(38) Go开发者(36) React(33) Go基础(29) Python(24) Vue(22) Web开发(20) Web技术(19) 精选资源(19) 深度学习(19) Java(18) ChatGTP(17) Cookie(16) android(16) 前端框架(13) JavaScript(13) Next.js(12) 安卓(11) typescript(10) 资料精选(10) NLP(10) 第三方Cookie(9) Redwoodjs(9) LLMOps(9) Go语言中级开发(9) 自然语言处理(9) 聊天机器人(9) PostgreSQL(9) 区块链(9) mlops(9) 安全(9) 全栈开发(8) ChatGPT(8) OpenAI(8) Linux(8) AI(8) GraphQL(8) iOS(8) 软件架构(7) Go语言高级开发(7) AWS(7) C++(7) 数据科学(7) whisper(6) Prisma(6) 隐私保护(6) RAG(6) JSON(6) DevOps(6) 数据可视化(6) wasm(6) 计算机视觉(6) 算法(6) Rust(6) 微服务(6) 隐私沙盒(5) FedCM(5) 语音识别(5) Angular开发(5) 快速应用开发(5) 提示工程(5) Agent(5) LLaMA(5) 低代码开发(5) Go测试(5) gorm(5) REST API(5) 推荐系统(5) WebAssembly(5) GameDev(5) CMS(5) CSS(5) machine-learning(5) 机器人(5) 游戏开发(5) Blockchain(5) Web安全(5) Kotlin(5) 低代码平台(5) 机器学习资源(5) Go资源(5) Nodejs(5) PHP(5) Swift(5) 智能体(4) devin(4) Blitz(4) javascript框架(4) Redwood(4) GDPR(4) 生成式人工智能(4) Angular16(4) Alpaca(4) SAML(4) JWT(4) JSON处理(4) Go并发(4) kafka(4) 移动开发(4) 移动应用(4) security(4) 隐私(4) spring-boot(4) 物联网(4) nextjs(4) 网络安全(4) API(4) Ruby(4) 信息安全(4) flutter(4) 专家智能体(3) Chrome(3) CHIPS(3) 3PC(3) SSE(3) 人工智能软件工程师(3) LLM Agent(3) Remix(3) Ubuntu(3) GPT4All(3) 软件开发(3) 问答系统(3) 开发工具(3) 最佳实践(3) RxJS(3) SSR(3) Node.js(3) Dolly(3) 移动应用开发(3) 编程语言(3) 低代码(3) IAM(3) Web框架(3) CORS(3) 基准测试(3) Go语言数据库开发(3) Oauth2(3) 并发(3) 主题(3) Theme(3) earth(3) nginx(3) 软件工程(3) azure(3) keycloak(3) 生产力工具(3) gpt3(3) 工作流(3) C(3) jupyter(3) 认证(3) prometheus(3) GAN(3) Spring(3) 逆向工程(3) 应用安全(3) Docker(3) Django(3) R(3) .NET(3) 大数据(3) Hacking(3) 渗透测试(3) C++资源(3) Mac(3) 微信小程序(3) Python资源(3) JHipster(3) 大型语言模型(2) 语言模型(2) 可穿戴设备(2) JDK(2) SQL(2) Apache(2) Hashicorp Vault(2) Spring Cloud Vault(2) Go语言Web开发(2) Go测试工程师(2) WebSocket(2) 容器化(2) AES(2) 加密(2) 输入验证(2) ORM(2) Fiber(2) Postgres(2) Gorilla Mux(2) Go数据库开发(2) 模块(2) 泛型(2) 指针(2) HTTP(2) PostgreSQL开发(2) Vault(2) K8s(2) Spring boot(2) R语言(2) 深度学习资源(2) 半监督学习(2) semi-supervised-learning(2) architecture(2) 普罗米修斯(2) 嵌入模型(2) productivity(2) 编码(2) Qt(2) 前端(2) Rust语言(2) NeRF(2) 神经辐射场(2) 元宇宙(2) CPP(2) 数据分析(2) spark(2) 流处理(2) Ionic(2) 人体姿势估计(2) human-pose-estimation(2) 视频处理(2) deep-learning(2) kotlin语言(2) kotlin开发(2) burp(2) Chatbot(2) npm(2) quantum(2) OCR(2) 游戏(2) game(2) 内容管理系统(2) MySQL(2) python-books(2) pentest(2) opengl(2) IDE(2) 漏洞赏金(2) Web(2) 知识图谱(2) PyTorch(2) 数据库(2) reverse-engineering(2) 数据工程(2) swift开发(2) rest(2) robotics(2) ios-animation(2) 知识蒸馏(2) 安卓开发(2) nestjs(2) solidity(2) 爬虫(2) 面试(2) 容器(2) C++精选(2) 人工智能资源(2) Machine Learning(2) 备忘单(2) 编程书籍(2) angular资源(2) 速查表(2) cheatsheets(2) SecOps(2) mlops资源(2) R资源(2) DDD(2) 架构设计模式(2) 量化(2) Hacking资源(2) 强化学习(2) flask(2) 设计(2) 性能(2) Sysadmin(2) 系统管理员(2) Java资源(2) 机器学习精选(2) android资源(2) android-UI(2) Mac资源(2) iOS资源(2) Vue资源(2) flutter资源(2) JavaScript精选(2) JavaScript资源(2) Rust开发(2) deeplearning(2) RAD(2)

在本教程中,我们将介绍 Go 中的指针以及如何在自己的 Go 程序中使用它们。我们将介绍最佳实践,并介绍一些最常见的指针用例。

在本教程结束时,您将对指针以及如何使用它们有一个扎实的理解。

介绍


在 Go 中,当我们调用一个函数并将一堆参数传递给该函数时,该语言会创建参数的副本,然后在所述函数中使用这些副本。例如:

main.go

package main

import "fmt"

func myTestFunc(a int) {
    a += 3
    fmt.Println(a)
}

func main() {
    a := 2
    myTestFunc(a)
    fmt.Println(a) // prints out 2
}

在上面的代码中,myTestFunc 接收一个整数变量,并对其进行复制,以便在函数体的上下文中使用。我们对 myTestFunc 中的 a 所做的任何更改都只会保留在 myTestFunc 函数的主体中。

现在,假设我们想调用 myTestFunc 并更新原来的 a 变量并将 3 添加到它?

在这个特定的例子中,我们可以更改函数签名,以便它接收指针而不是引用。这意味着我们在 myTestFunc 函数中对 a 所做的任何更改都将针对原始变量而不是副本!

main.go

package main

import "fmt"

func myTestFunc(a *int) {
    a += 3
    fmt.Println(a)
}

func main() {
    a := 2
    myTestFunc(a)
    fmt.Println(a) // prints out 5
}

当我们运行上面的代码时,我们应该看到 myTestFunc 已经正确更新了 a 的原始值并添加了 3:

$ go run main.go

5
5


定义指针


现在让我们退后一步,看看使用指针的基础知识。

我们将从查看如何在 Go 代码中定义指针开始。为了定义一个指针,我们可以在我们声明变量的地方使用 * 符号,它将把变量变成一个指针变量。

main.go

package main

import "fmt"

func main() {
    var age *int

    fmt.Println(age)
    fmt.Println(&age)
}

当我们尝试运行它时?我们应该看到以下内容:

$ go run main.go

<nil>
0xc00000e018


第一个值代表我们的指针变量age的值。第二个代表这个变量的地址。

给指针赋值


问题 - 如果您尝试为年龄分配值会发生什么?

就目前而言,我们的年龄变量为零。让我们尝试将其设置为 26,看看会发生什么:

main.go

package main

import "fmt"

func main() {
    var age *int

    *age = 26

    fmt.Println(age)
    fmt.Println(&age)
}

这实际上会导致编译器恐慌。

$ go run main.go

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x1092f6e]

goroutine 1 [running]:
main.main()
        /Users/elliot/Documents/Projects/TutorialEdge/Projects/Go/go-pointers-tutorial/main.go:8 +0x3e
exit status 2

这样做的原因是我们需要使用内置函数 new 来分配足够的内存来容纳 int 类型的值。现在让我们看看它的实际效果:

package main

import "fmt"

func main() {
    var age *int
	age = new(int)
	*age = 26

    fmt.Println(*age)
    fmt.Println(&age)
}

重要提示 - 如果我们希望更简洁一点,我们可以删除上面示例中 main 函数的第一行并将 age = new(int) 修改为 age := new(int) 。

可空性(Nullability)


重要提示 - 在 Go 代码中使用指针的一大优势是它们可以为空。

如果我们有一个具有指针返回值的函数,我们可以利用指针可以为空这一事实。

以第一个函数为例:

func testFunc(id string) (Guitarist, error) {
    result, err := getSongs(id)
    if err != nil {
        return Guitarist{}, err
    }

    return result, nil
}

在上面的代码中,我们必须填充一个空的 Guitarist{} 结构来返回错误。然而,如果我们用一个指针返回值来定义这个函数,那么我们可以像这样简化上面的代码:

func testFunc(id string) (*Guitarist, error) {
    result, err := getSongs(id)
    if err != nil {
        return nil, err
    }

    return result, nil
}

传递变量

在教授 Go 时,我经常看到开发人员在如何将指针变量传递给接受值接收器的函数时遇到了困难。让我们看一个例子:

main.go

package main

import "fmt"

func YearsUntilRetirement(age int) {
    fmt.Println(100 - age)
}

func main() {
	var age *int
	age = new(int)
	*age = 26
    
    YearsUntilRetirement(age)
}

当我们尝试运行它时,我们应该看到它抱怨我们不能将类型 *int 传递给我们的函数 YearsUntilRetirement。

$ go run main.go

## command-line-arguments
./main.go:13:25: cannot use age (type *int) as type int in argument to YearsUntilRetirement


为了传递这个指针的值,我们可以通过将它作为 *age 传递给我们的函数来取消引用,如下所示:

main.go

package main

import "fmt"

func YearsUntilRetirement(age int) {
    fmt.Println(100 - age)
}

func main() {
	var age *int
	age = new(int)
	*age = 26
    
    YearsUntilRetirement(*age)
}

现在,当我们运行它时,我们应该看到我们的 Go 应用程序执行了!

$ go run main.go

74


结论


太棒了,所以在本教程中,我们介绍了 Go 中指针的基础知识,以及如何在自己的 Go 应用程序中使用和滥用它们!

希望您发现本教程有用且有趣,如果您这样做了,或者您有任何其他意见或问题,请随时在下面的评论部分告诉我!

文章链接