首页 > 其他分享 >Go指针进阶:从入门到被虐,90%开发者都踩过这些坑

Go指针进阶:从入门到被虐,90%开发者都踩过这些坑

时间:2024-12-11 13:33:38浏览次数:11  
标签:return 进阶 int func 90% Go type 指针

Go指针进阶:从入门到被虐,90%开发者都踩过这些坑!

原创 瀛洲在线编程之道 黑客编程之道    2024年11月17日 21:10 吉林 听全文 黑客编程之道 分享黑客编程技术,Go、Python、Rust、Java等编程技术 166篇原创内容 公众号

指针是Go语言中最强大但也最容易出错的特性之一。本文将带你从基础概念到高级应用,全方位掌握Go指针的使用技巧。无论你是初学者还是老手,都能在这里找到价值。

一、指针基础:从零开始

  1. 什么是指针?
Go语言中的指针是一个用来存储变量内存地址的变量,可以使用 & 运算符获取变量的地址,使用 * 运算符获取指针所指向的变量的值,可以进行运算来移动指针。
var a int = 10var p *int = &a  // p存储的是a的内存地址fmt.Printf("a的值:%d\n", a)        // 10fmt.Printf("a的地址:%p\n", &a)     // 0xc0000120b0fmt.Printf("p的值:%p\n", p)        // 0xc0000120b0fmt.Printf("p指向的值:%d\n", *p)    // 10

2. 指针的零值

var p *int  // p的零值是nilif p == nil {    fmt.Println("空指针")}
二、常见陷阱:血的教训
  1. 空指针解引用
// 错误示例var p *int*p = 1  // panic: runtime error: invalid memory address or nil pointer dereference
// 正确做法var p *int = new(int)*p = 1

2. 返回局部变量的指针

// Go中这样是安全的!func newInt() *int {    v := 42    return &v  // Go会自动将v逃逸到堆上}
// 但这样可能有问题func dangerous() *int { v := 42 p := &v return p}

三、高级用法:解锁新技能

  1. 指针数组与数组指针
// 指针数组:元素是指针的数组arr := [3]*int{}a, b, c := 1, 2, 3arr[0], arr[1], arr[2] = &a, &b, &c
// 数组指针:指向数组的指针arr2 := &[3]int{1, 2, 3}

2. 结构体指针

type Person struct {    Name string    Age  int}
// 方法一:常规创建p1 := &Person{ Name: "张三", Age: 25,}
// 方法二:new关键字p2 := new(Person)p2.Name = "李四" // 自动解引用,等同于 (*p2).Name = "李四"
四、性能优化:指针还是值?
  1. 传值vs传指针
// 大结构体:用指针type BigStruct struct {    Data [1024]int}
func processPointer(b *BigStruct) { // 只传递8字节指针}
// 小结构体:直接传值type SmallStruct struct { A, B int}
func processValue(s SmallStruct) { // 直接传值更快}
2. 切片的隐式指针
// 切片本身包含指针type slice struct {    array unsafe.Pointer    len   int    cap   int}
// 因此传递切片无需使用指针func process(s []int) { // 直接传切片}
五、实战技巧:进阶操作

  1. 指针池化
var pool = sync.Pool{    New: func() interface{} {        return &bytes.Buffer{}    },}
func process() { buf := pool.Get().(*bytes.Buffer) defer pool.Put(buf) buf.Reset() // 使用buf}
2. 原子操作中的指针
type Config struct {    Features map[string]bool}
var configPtr atomic.Value
// 原子更新配置func updateConfig(c *Config) { configPtr.Store(c)}
// 原子读取配置func getConfig() *Config { return configPtr.Load().(*Config)}
六、安全编程:防患未然
  1. 空指针检查
func safeDereference(p *int) int {    if p == nil {        return 0 // 默认值    }    return *p}
2. 接口与指针
type Worker interface {    Work()}
type Employee struct { Name string}
// 使用指针接收者实现接口func (e *Employee) Work() { fmt.Printf("%s is working\n", e.Name)}
// 注意:此时只有指针类型实现了接口var w Workere := Employee{Name: "张三"}//w = e // 编译错误!w = &e // 正确
七、高级应用:骚操作
  1. 指针运算(不推荐)
// 使用unsafe包进行指针运算p := unsafe.Pointer(&arr[0])p = unsafe.Pointer(uintptr(p) + unsafe.Sizeof(arr[0]))
2. 类型转换
// 字符串转字节切片(零拷贝)func stringToBytes(s string) []byte {    return *(*[]byte)(unsafe.Pointer(        &struct {            string            Cap int        }{s, len(s)}))}
八、实用模式:设计技巧
  1. 函数选项模式
type options struct {    timeout time.Duration    retries int}
type Option func(*options)
func WithTimeout(t time.Duration) Option { return func(o *options) { o.timeout = t }}
2. 构建者模式
type Builder struct {    msg *Message}
func (b *Builder) AddHeader(h string) *Builder { b.msg.Header = h return b}
九、调试技巧:排查问题
  1. 打印指针信息
fmt.Printf("指针值:%p\n", p)fmt.Printf("指针类型:%T\n", p)fmt.Printf("指针指向的值:%+v\n", *p)
2. race检测
go run -race main.go
总结指针使用的黄金法则:
  1. 大结构体传递用指针

  2. 需要修改接收者的方法用指针接收者

  3. 小结构体直接传值

  4. 注意空指针检查

  5. 合理使用sync.Pool管理指针对象
踩坑提醒:
  1. 警惕nil指针解引用

  2. 注意垃圾回收

  3. 谨慎使用unsafe包

  4. 关注并发安全
进阶建议:
  1. 理解逃逸分析

  2. 掌握内存模型

  3. 熟悉性能特征

  4. 注意接口的实现约束
如果你觉得这篇文章有帮助,欢迎点赞转发,也欢迎在评论区分享你的见解和经验!

标签:return,进阶,int,func,90%,Go,type,指针
From: https://www.cnblogs.com/cheyunhua/p/18599294

相关文章

  • VSCode开发Go入门
    一、Go环境搭建安装Go使用国内的Go语言中文网 https://studygolang.com/dl 进行下载找到合适的平台点击链接下载即可,这里以Windows为例下载完成后点击安装保持默认即可安装后Go将自动设置环境变量,打开终端或CMD窗口验证Go命令是否可用goversion若安装......
  • Mongodb安装
    下载地址https://www.mongodb.com/try/download/community安装步骤next安装选择custom版本选好安装地址,一路next配置环境path添加bin;在data目录新建db文件夹运行dos运行以下命令mongod--dbpath复制过来的db文件夹路径测试是否运行成功设置开机启动设置好一......
  • 怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
    本文引用怎么禁用vscode中点击go包名时自动打开浏览器跳转到pkg.go.dev在vscode设置项中配置gopls的ui.navigation.importShortcut为Definition即可。"gopls":{"ui.navigation.importShortcut":"Definition"}ui.navigation.importShortcut接受的值:"......
  • shodan(3)命令进阶及VNC空密码实战
    本篇文章旨在为网络安全初学者介绍渗透测试行业信息收集的引擎。通过阅读本文,读者将能够对shodan引擎工具的使用有一个初步的了解一、命令进阶1、查询平台漏洞数量shodancount'"\x03\x00\x00\x0b\x06\xd0\x00\x00\x124\x00"'2、过滤IP地址(vuln需要shodan高级账号......
  • 无敌飞舞Hanggoash的总结贴
    无敌飞舞Hanggoash的总结贴一定要学会根据数据范围推复杂度。卡题15分钟就先跳(指202410-11月时常不能切掉div2c)切忌倒序开题,现在暂时没有那个本事。(CF984rk9600)少看榜(至少目前为止不需要)ifelse一定要写大括号,并且严禁压行。交互题最好就只写cincout,endl本身就具有刷......
  • sentinel go 熔断降级
    Overview在高可用设计中,除了流控外,对分布式系统调用链路中不稳定的资源(比如RPC服务等)进行熔断降级也是保障高可用的重要措施之一。现在的分布式架构中一个服务常常会调用第三方服务,这个第三方服务可能是另外的一个RPC接口、数据库,或者第三方API等等。例如,支付的时候,可能需......
  • 流量控制 (Sentinel Go)
    Overview流量控制(flowcontrol),其原理是监控资源(Resource)的统计指标,然后根据token计算策略来计算资源的可用token(也就是阈值),然后根据流量控制策略对请求进行控制,避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。SentinelGo的流量控制实现代码参考:https://github.......
  • go项目在linux中用yum命令安装telnet
    在Linux系统上,如果你使用的是基于**RedHat**(如RHEL、CentOS、Fedora等)的发行版,可以通过`yum`命令安装Telnet客户端。以下是步骤:方法1:1,先检查是否安装了telnet:rpm-qa|greptelnet2.然后检查yum列表里面有什么yumlist|greptelnet3、安装yuminstall......
  • 网站logo地址哪里修改,如何在网站中修改logo地址
    网站的Logo是品牌形象的重要组成部分,修改Logo地址可以帮助您更新品牌形象或适应新的设计需求。以下是详细的步骤和技巧:备份数据:在进行任何修改前,备份网站的数据和代码,防止意外丢失。使用FTP客户端下载网站的全部文件,并导出数据库。准备新的Logo:准备一个新的Logo图像文......
  • php网站后台修改logo,如何轻松更新PHP网站的LOGO
    如果您需要修改PHP网站的LOGO,可以按照以下步骤进行操作:准备新LOGO图片:首先,准备好您想要使用的LOGO图片。确保图片格式为PNG或SVG,并且大小适中以减少加载时间。登录FTP客户端:使用FTP客户端(如FileZilla)连接到您的服务器。上传LOGO图片:将新LOGO图片上传到网站的图片目录。通......