大家好,我是建宇。在日常的Go项目开发中,我们经常会使用fmt.Printf或者fmt.Sprintf来编写类似拼接字符串的业务。以下代码:fmt.Printf("HelloGopher%s,youare%dyearsoldandyou'refavoritefoodis%s",name,age,favoriteFood)这个业务是迭代迭代的,随着时间的推移积累,一些其中不断变化的装配逻辑会越来越长。小型计算机屏幕不再足以在一行中显示代码。将字符串转为变量的特性有很多,但是后面又臭又长的一串变量又不能轻易丢弃,所以大部分同学会选择格式化代码。下面的代码:s:="HelloGopher%s,youare%dyearsoldandyou'refavoritefoodis%s"fmt.Printf(s,name,age,favoriteFood,)你可能认为这是一个例子?其实不是,很多人都遇到过。简单的字符串插值这个在Goissues社区已经讨论了三四年了,@IanLanceTaylor发起了一个新的提案《proposal: spec: add simple string interpolation similar to Swift》。希望得到更多的讨论和增加新的功能来解决这个问题。这个新功能类似于Swift中字符串插值的更简单版本。直接看例子:fmt.Println("\(person.Name())是\(person.Age())岁")fmt.Println("时间是\(time.Now().Round(0))")对应输出:KenThompson79岁时间为2023-01-0416:22:01.204034106-0800PSTProposal计划增加“字符串插值”,规范如下:新的转义语法:\(xxxx),以\(开头,以)结尾,成对出现。在格式方面,有效的\(必须后跟表达式和尾随)才能生效。上面的例子中,下面都是字符串插值:\(person.Name())\(person.Age())\(time.Now().Round(0))有同学会疑惑,像person怎么办它看起来像一个结构?Go有一个神奇的约定方法,其中像结构这样的类型,如果它们有一个String()字符串方法,将被调用以获取字符串值。如果没有String方法,需要是字符串、整数、浮点数、复数、常量或布尔值,取值后可以格式化。否则会报错。其他语言例子Swiftletmultiplier=3letmessage="\(multiplier)times2.5is\(Double(multiplier)*2.5)"//messageis"3times2.5is7.5"Kotlinvarage=21println("MyAgeIs:$age")Cstringname="Mark";vardate=DateTime.Now;Console.WriteLine($"你好,{name}!今天是{date.DayOfWeek},现在是{date:HH:mm}。");Rustletperson=get_person();println!("你好,{person}!");//捕获本地的`person`println!("Hello,{}!",get_person());//隐式位置println!("你好,{0}!",get_person());//显式indexprintln!("你好,{person}!",person=get_person());//namedlet(width,precision)=get_format();for(name,score)inget_scores(){println!("{name}:{score:width$.precision$}");}争议目前主要争论之一,fmt.Sprintf等方法也可以完成字符串插值完全一样的效果,为什么要加这个功能(或者说语法糖)?主流观点认为,现有的格式化字符串的方法在参数过多时容易出错(例如:顺序错误),而且比较松散,代码量大。加入了字符串插值的特性/语法糖后,可以更好的读取和修改,不必过多依赖变量的书写顺序,更加紧凑。具体示例如下,现有版本代码:errorf(pos,"argumentstocopy%sand%shavedifferentelementtypes%sand%s",x,&y,dst.elem,src.elem)应用后新特性会变成:error(pos,"argumentstocopy\(x)and\(&y)havedifferentelementtypes\(dst.elem)and\(src.elem)")综上所述,我们经常遇到在ourwork对于这个问题,甚至有同学在issues中反映,他经常要写50多个参数的格式化参数,在Go中维护起来比较痛苦。如果您是长期维护某些项目的开发人员,您将不断添加和更改现有的格式化字符串方法,以及新的字符串插值。未来几年你会选择哪一个?或者你有什么新的想法吗?文章持续更新中。可以微信搜索【脑补炸鱼】阅读。本文已收录在GitHubgithub.com/eddycjy/blog中。学习Go语言可以看Go学习地图和路线。欢迎星星提醒。Go书系列Go语言入门系列:初探Go项目实战Go语言编程之旅:深入使用Go做项目Go语言设计哲学:理解Go的Why与设计思维Go语言进阶之旅:进一步深入-深度围棋源码推荐阅读增加实力!Go将增强Go1的向后兼容性。兄弟们,Go1.20竞技场来了!Go十年,终于想起统一日志库!
