当前位置: 首页 > news >正文

go中常见的错误-以及泛型

https://github.com/teivah/100-go-mistakes#table-of-contents
nil Map
map记得要make初始化, slice可以不用初始化!

func main() {
//assignment to nil map
var course map[string]string //如果不初始化,就会为nilcourse["name"] = "go体系课"
}

结构体空指针
空结构体和结构体空指针可不一样

type Course struct {Name stringDesc string
}
func (c *Course) String() float64 {return c.Name + c.Desc
}
func main() {var c *Course //无效的内存地址或空指针解引用fmt.Println(c.String())
}
//结构体空指针 指针类型一定要初始化,否则nil
//var c *Couser 
c := &Couser{} // new(Couser)

使用对循环迭代器变量的引用 - 大坑!
在 Go 中,循环迭代器变量是一个单一的变量,在每个循环迭代中取不同的值。这如果使用不当,可能会导致非预期的行为。

func main() {var out []*intfor i := 0; i < 3; i++ {out = append(out, &i)}fmt.Println("Values:", *out[0], *out[1], *out[2])fmt.Println("Addresses:", out[0], out[1], out[2])
}
func main() {var out []*int//for循环的临时变量会复用for i := 0; i < 3; i++ {out = append(out, &i)}fmt.Println(out) //[0xc00000a0c8 0xc00000a0c8 0xc00000a0c8]for _, value := range out {fmt.Println(*value) //3 3 3}
}

解决办法

func main() {var out []*intfor i := 0; i < 3; i++ {tmpi := iout = append(out, &tmpi)}fmt.Println("Values:", *out[0], *out[1], *out[2])fmt.Println("Addresses:", out[0], out[1], out[2])
}

原因是:在每次迭代中,我们将 i 的地址追加到 out 切片中,但由于它是同一个变量,我们实际上追加的是相同的地址,该地址最终包含分配给 i 的最后一个值。所以只需要拷贝一份,让两者脱离关联就可以了。同样的,如果这里是for循环然后启动多个goroutine, 如下:

package main
import ("fmt""strconv""time"
)func main() {goodsID := []uint64{1, 2, 3, 4, 5}for _, id := range goodsID {go func() {fmt.Println("正在查询商品:" + strconv.Itoa(int(id)))}()}time.Sleep(time.Second * 5)
}

注意:这种bug在goland中一般会提醒,
常用的解决办法:

import ("fmt""strconv""time"
)func main() {goodsID := []uint64{1, 2, 3, 4, 5}for _, id := range goodsID {tmp := idgo func() {fmt.Println("正在查询商品:" + strconv.Itoa(int(tmp)))}()}time.Sleep(time.Second * 5)
}
package mainimport ("fmt""strconv""time"
)func main() {goodsID := []uint64{1, 2, 3, 4, 5}for _, id := range goodsID {//值传递go func(id uint64) {fmt.Println("正在查询商品:" + strconv.Itoa(int(id)))}(id)}time.Sleep(time.Second * 5)
}

go如何使用泛型

package mainfunc Add[T int | int32 | float32 | float64 | uint64](a, b T) T {return a + b
}// IAdd  没有泛型之前
func IAdd(a, b interface{}) interface{} {switch a.(type) {case int:return a.(int) + b.(int)case int32:return a.(int32) + b.(int32)case float32:return a.(float32) + b.(float32)}return nil
}func main() {//print(Add[float32](1.2, 2.2))t := IAdd(1, 2).(int)print(t)
}

泛型的常见用法

package maintype Mymap[KEY int | string, VALUE float32 | float64] map[KEY]VALUEtype Man struct {
}type Woman struct {
}type Company[T Man | Woman] struct {Name stringCEO  T
}type MyChannel[T int | string] chan T// WowStruct 类型嵌套
type WowStruct[T string | int, S []T] struct {A TB S
}func main() {/*m:=Mymap[int,float32]{}*///company := Company[Man]{//	Name: "chengpeng",//	CEO:  Man{},//}////company1 := Company[Woman]{//	Name: "chengpeng",//	CEO:  Man{},//}var c MyChannel[string]
}

泛型的错误用法

//错误用法1 类型参数不能单独使用
//type CommonType[T int | string] Ttype CommonType[T int | string] []T//错误用法2 无效的数组绑定 'T *int | string',必须是一个常量表达式
//type CommonType1[T *int | string] []Ttype CommonType1[T interface{ *int } | string] []T

匿名接口体不支持泛型–错误用法3

test:= struct[t int|string] {Name stringAge int
}{}

匿名函数不支持泛型–错误用法3

fn := func[T int | float64](a, b T) {
}

泛型不支持switch断言,但是可以用反射去做做法不提倡—错误用法4

func Add1[T int | int32 | float32 | float64 | uint64](a, b T) T {v := reflect.ValueOf(a)switch v.Kind() {case reflect.Int:print("int type")}return a + b
}

相关文章:

  • DeepFloyd IF:由文本生成图像的强大模型,能够绘制文字的 AI 图像工具
  • 9.5.1 函数模板特化
  • 使用Android Compose实现网格列表滑到底部的提示信息展示
  • 常用Java代码-Java中的并发集合(ConcurrentHashMap、CopyOnWriteArrayList等)
  • Sqoop的增量数据加载策略与示例
  • 解决Unexpected record signature 0X9maven 资源过滤
  • jar包部署到linux虚拟机的docker中之后连不上mysql
  • 【Spring实战】28 @Autowired 和 @Resource注解的区别与使用
  • Linux完全卸载Anaconda3和MiniConda3
  • 索引的概述和使用
  • 线性代数——(期末突击)概率统计习题(概率的性质、全概率公式)
  • YOLOv5改进 | 注意力篇 | CGAttention实现级联群体注意力机制 (全网首发改进)
  • 智能路由器 端口映射 (UPnP) Padavan内网端口映射配置方法
  • 山西电力市场日前价格预测【2024-01-13】
  • openssl3.2 - 官方demo学习 - cms - cms_sign.c
  • (三)从jvm层面了解线程的启动和停止
  • [case10]使用RSQL实现端到端的动态查询
  • 【comparator, comparable】小总结
  • 【划重点】MySQL技术内幕:InnoDB存储引擎
  • 4月23日世界读书日 网络营销论坛推荐《正在爆发的营销革命》
  • angular2开源库收集
  • ES6之路之模块详解
  • HTML5新特性总结
  • Java 网络编程(2):UDP 的使用
  • Laravel 菜鸟晋级之路
  • Laravel 中的一个后期静态绑定
  • Quartz实现数据同步 | 从0开始构建SpringCloud微服务(3)
  • React-flux杂记
  • TCP拥塞控制
  • Vue 动态创建 component
  • webpack4 一点通
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 基于阿里云移动推送的移动应用推送模式最佳实践
  • 前端相关框架总和
  • 思维导图—你不知道的JavaScript中卷
  • 微服务核心架构梳理
  • 我与Jetbrains的这些年
  • 小程序上传图片到七牛云(支持多张上传,预览,删除)
  • 源码安装memcached和php memcache扩展
  • Unity3D - 异步加载游戏场景与异步加载游戏资源进度条 ...
  • 积累各种好的链接
  • 交换综合实验一
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​ssh免密码登录设置及问题总结
  • # Kafka_深入探秘者(2):kafka 生产者
  • #绘制圆心_R语言——绘制一个诚意满满的圆 祝你2021圆圆满满
  • (2)STM32单片机上位机
  • (23)Linux的软硬连接
  • (4) PIVOT 和 UPIVOT 的使用
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (杂交版)植物大战僵尸
  • (转) Face-Resources
  • (转)VC++中ondraw在什么时候调用的
  • .NET 8 编写 LiteDB vs SQLite 数据库 CRUD 接口性能测试(准备篇)
  • .NET BackgroundWorker