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

惠州网站营销推广网站快速优化排名

惠州网站营销推广,网站快速优化排名,专门做网站的公司 南阳,做网站流量优化都是什么关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力! 在开发生产项目的过程中,我注意到经常会发现自己在重复编写代码,使用某些技巧时没有意识到,直…

关注公众号【爱发白日梦的后端】分享技术干货、读书笔记、开源项目、实战经验、高效开发工具等,您的关注将是我的更新动力!

在开发生产项目的过程中,我注意到经常会发现自己在重复编写代码,使用某些技巧时没有意识到,直到后来回顾工作时才意识到。

为了解决这个问题,我开发了一种解决方案,对我来说非常有帮助,我觉得对其他人也可能有用。

以下是一些从我的实用程序库中随机挑选的有用且多功能的代码片段,没有特定的分类或特定于系统的技巧。

1. 追踪执行时间的技巧

如果你想追踪 Go 中函数的执行时间,有一个简单高效的技巧可以用一行代码实现,使用 defer 关键字即可。你只需要一个 TrackTime 函数:

// Utility
func TrackTime(pre time.Time) time.Duration {elapsed := time.Since(pre)fmt.Println("elapsed:", elapsed)return elapsed
}func TestTrackTime(t *testing.T) {defer TrackTime(time.Now()) // <--- THIStime.Sleep(500 * time.Millisecond)
}// 输出:
// elapsed: 501.11125ms

1.5. 两阶段延迟执行

Go 的 defer 不仅仅是用于清理任务,还可以用于准备任务,考虑以下示例:

func setupTeardown() func() {fmt.Println("Run initialization")return func() {fmt.Println("Run cleanup")}
}func main() {defer setupTeardown()() // <--------fmt.Println("Main function called")
}// 输出:
// Run initialization
// Main function called
// Run cleanup

这种模式的美妙之处在于,只需一行代码,你就可以完成诸如以下任务:

  • 打开数据库连接,然后关闭它。
  • 设置模拟环境,然后拆除它。
  • 获取分布式锁,然后释放它。

“嗯,这似乎很聪明,但它在现实中有什么用处呢?”

还记得追踪执行时间的技巧吗?我们也可以这样做:

func TrackTime() func() {pre := time.Now()return func() {elapsed := time.Since(pre)fmt.Println("elapsed:", elapsed)}
}func main() {defer TrackTime()()time.Sleep(500 * time.Millisecond)
}

注意!如果我连接到数据库时出现错误怎么办?

确实,像 defer TrackTime()defer ConnectDB() 这样的模式不会妥善处理错误。这种技巧最适合用于测试或者当你愿意冒着致命错误的风险时使用,参考下面这种面向测试的方法:

func TestSomething(t *testing.T) {defer handleDBConnection(t)()// ...
}func handleDBConnection(t *testing.T) func() {conn, err := connectDB()if err != nil {t.Fatal(err)}return func() {fmt.Println("Closing connection", conn)}
}

这样,在测试期间可以处理数据库连接的错误。

2. 预分配切片

根据文章《Go 性能提升技巧》中的见解,预分配切片或映射可以显著提高 Go 程序的性能。

但是值得注意的是,如果我们不小心使用 append 而不是索引(如 a[i]),这种方法有时可能导致错误。你知道吗,我们可以在不指定数组长度(为零)的情况下使用预分配的切片,就像在上述文章中解释的那样?这使我们可以像使用 append 一样使用预分配的切片:

// 与其
a := make([]int, 10)
a[0] = 1// 不如这样使用
b := make([]int, 0, 10)
b = append(b, 1)

3. 链式调用

链式调用技术可以应用于函数(指针)接收器。为了说明这一点,让我们考虑一个 Person 结构,它有两个函数 AddAgeRename,用于对其进行修改。

type Person struct {Name stringAge  int
}func (p *Person) AddAge() {p.Age++
}func (p *Person) Rename(name string) {p.Name = name
}

如果你想给一个人增加年龄然后给他们改名字,常规的方法是:

func main() {p := Person{Name: "Aiden", Age: 30}p.AddAge()p.Rename("Aiden 2")
}

或者,我们可以修改 AddAgeRename 函数接收器,使其返回修改后的对象本身,即使它们通常不返回任何内容。

func (p *Person) AddAge() *Person {p.Age++return p
}func (p *Person) Rename(name string) *Person {p.Name = namereturn p
}

通过返回修改后的对象本身,我们可以轻松地将多个函数接收器链在一起,而无需添加不必要的代码行:

p = p.AddAge().Rename("Aiden 2")

4. Go 1.20 允许将切片解析为数组或数组指针

当我们需要将切片转换为固定大小的数组时,不能直接赋值,例如:

a := []int{0, 1, 2, 3, 4, 5}
var b [3]int = a[0:3]// 在变量声明中不能将 a[0:3](类型为 []int 的值)赋值给 [3]int 类型的变量
// (不兼容的赋值)

为了将切片转换为数组,Go 团队在 Go 1.17 中更新了这个特性。随着 Go 1.20 的发布,借助更方便的字面量,转换过程变得更加简单:

// Go 1.20
func Test(t *testing.T) {a := []int{0, 1, 2, 3, 4, 5}b := [3]int(a[0:3])fmt.Println(b) // [0 1 2]
}// Go 1.17
func TestM2e(t *testing.T) {a := []int{0, 1, 2, 3, 4, 5}b := *(*[3]int)(a[0:3])fmt.Println(b) // [0 1 2]
}

只是一个快速提醒:你可以使用 a[:3] 替代 a[0:3]。我提到这一点是为了更清晰地说明。

5. 使用 “import _” 进行包初始化

有时,在库中,你可能会遇到结合下划线 (_) 的导入语句,如下所示:

import (_ "google.golang.org/genproto/googleapis/api/annotations"
)

这将执行包的初始化代码(init 函数),而无需为其创建名称引用。这允许你在运行代码之前初始化包、注册连接和执行其他任务。

让我们通过一个示例来更好地理解它的工作原理:

// 下划线
package underscorefunc init() {fmt.Println("init called from underscore package")
}
// main
package mainimport (_ "lab/underscore"
)func main() {}
// 输出:init called from underscore package

6. 使用 “import .” 进行导入

在了解了如何使用下划线进行导入后,让我们看看如何更常见地使用点 (.) 运算符。

作为开发者,点 (.) 运算符可用于在不必指定包名的情况下使用导入包的导出标识符,这对于懒惰的开发者来说是一个有用的快捷方式。

很酷,对吧?这在处理项目中的长包名时特别有用,比如 externalmodeldoingsomethinglonglib

为了演示,这里有一个简单的例子:

package mainimport ("fmt". "math"
)func main() {fmt.Println(Pi) // 3.141592653589793fmt.Println(Sin(Pi / 2)) // 1
}

7. Go 1.20 允许将多个错误合并为单个错误

Go 1.20 引入了对错误包的新功能,包括对多个错误的支持以及对 errors.Is 和 errors.As 的更改。

errors 中添加的一个新函数是 Join,我们将在下面详细讨论它:

var (err1 = errors.New("Error 1st")err2 = errors.New("Error 2nd")
)func main() {err := err1err = errors.Join(err, err2)fmt.Println(errors.Is(err, err1)) // truefmt.Println(errors.Is(err, err2)) // true
}

如果有多个任务导致错误,你可以使用 Join 函数而不是手动管理数组。这简化了错误处理过程。

8. 检查接口是否为真正的 nil

即使接口持有的值为 nil,也不意味着接口本身为 nil。这可能导致 Go 程序中的意外错误。因此,重要的是要知道如何检查接口是否为真正的 nil

func main() {var x interface{}var y *int = nilx = yif x != nil {fmt.Println("x != nil") // <-- 实际输出} else {fmt.Println("x == nil")}fmt.Println(x)
}// 输出:
// x != nil
// <nil>

我们如何确定 interface{} 值是否为 nil 呢?幸运的是,有一个简单的工具可以帮助我们实现这一点:

func IsNil(x interface{}) bool {if x == nil {return true}return reflect.ValueOf(x).IsNil()
}

9. 在 JSON 中解析 time.Duration

当解析 JSON 时,使用 time.Duration 可能是一个繁琐的过程,因为它需要在一秒的后面添加 9 个零(即 1000000000)。为了简化这个过程,我创建了一个名为 Duration 的新类型:

type Duration time.Duration

为了将字符串(如 “1s” 或 “20h5m”)解析为 int64 类型的持续时间,我还为这个新类型实现了自定义的解析逻辑:

func (d *Duration) UnmarshalJSON(b []byte) error {var s stringif err := json.Unmarshal(b, &s); err != nil {return err}dur, err := time.ParseDuration(s)if err != nil {return err}*d = Duration(dur)return nil
}

但是,需要注意的是,变量 ‘d’ 不应为 nil,否则可能会导致编组错误。或者,你还可以在函数开头对 ‘d’ 进行检查。

10. 避免裸参数

当处理具有多个参数的函数时,仅通过阅读其用法来理解每个参数的含义可能会令人困惑。考虑以下示例:

printInfo("foo", true, true)

如果不检查 printInfo 函数,那么第一个 ‘true’ 和第二个 ‘true’ 的含义是什么呢?当你有一个具有多个参数的函数时,仅通过阅读其用法来理解参数的含义可能会令人困惑。

但是,我们可以使用注释使代码更易读。例如:

// func printInfo(name string, isLocal, done bool)printInfo("foo", true /* isLocal */, true /* done */)

有些 IDE 也支持这个功能,可以在函数调用建议中显示注释,但可能需要在设置中启用。

以上是我分享的一些实用技巧,但我不想让文章过长,难以跟进,因为这些技巧与特定主题无关,涵盖了各种类别。

如果你觉得这些技巧有用,或有自己的见解要分享,请随时留言。我重视你的反馈,并乐于在回应此文章时点赞或推荐你的想法。


文章转载自:
http://tercel.rkdw.cn
http://guestchamber.rkdw.cn
http://agrarianize.rkdw.cn
http://deimos.rkdw.cn
http://parang.rkdw.cn
http://pallbearer.rkdw.cn
http://textually.rkdw.cn
http://retranslate.rkdw.cn
http://lowliness.rkdw.cn
http://caterwauling.rkdw.cn
http://voetstoots.rkdw.cn
http://cheerleader.rkdw.cn
http://assurgent.rkdw.cn
http://ethnical.rkdw.cn
http://chibouk.rkdw.cn
http://highjacker.rkdw.cn
http://ahead.rkdw.cn
http://helvetic.rkdw.cn
http://dianetic.rkdw.cn
http://jaileress.rkdw.cn
http://cosmism.rkdw.cn
http://jeopardous.rkdw.cn
http://bacteremic.rkdw.cn
http://boart.rkdw.cn
http://blobberlipped.rkdw.cn
http://chorus.rkdw.cn
http://priestlike.rkdw.cn
http://denny.rkdw.cn
http://catachresis.rkdw.cn
http://hanap.rkdw.cn
http://plevna.rkdw.cn
http://disaggregation.rkdw.cn
http://heterometabolic.rkdw.cn
http://petiolule.rkdw.cn
http://tzarist.rkdw.cn
http://algometric.rkdw.cn
http://misarrangement.rkdw.cn
http://cheering.rkdw.cn
http://kitchensink.rkdw.cn
http://baconianism.rkdw.cn
http://procumbent.rkdw.cn
http://sirenian.rkdw.cn
http://flesh.rkdw.cn
http://curlycue.rkdw.cn
http://preaddict.rkdw.cn
http://viennese.rkdw.cn
http://ek.rkdw.cn
http://bajan.rkdw.cn
http://credited.rkdw.cn
http://quarterstaff.rkdw.cn
http://sinlessly.rkdw.cn
http://hectocotylus.rkdw.cn
http://leatherette.rkdw.cn
http://unseemly.rkdw.cn
http://thorax.rkdw.cn
http://immunoassay.rkdw.cn
http://cins.rkdw.cn
http://lockpin.rkdw.cn
http://lean.rkdw.cn
http://smatter.rkdw.cn
http://lixiviate.rkdw.cn
http://editioprinceps.rkdw.cn
http://postconsonantal.rkdw.cn
http://multivocal.rkdw.cn
http://extraventricular.rkdw.cn
http://eyen.rkdw.cn
http://extinction.rkdw.cn
http://schoolmiss.rkdw.cn
http://mystagogical.rkdw.cn
http://bunker.rkdw.cn
http://velites.rkdw.cn
http://believer.rkdw.cn
http://anthropogenesis.rkdw.cn
http://stook.rkdw.cn
http://recurve.rkdw.cn
http://granitiform.rkdw.cn
http://ldap.rkdw.cn
http://sou.rkdw.cn
http://surprize.rkdw.cn
http://ruderal.rkdw.cn
http://radicalize.rkdw.cn
http://zealousness.rkdw.cn
http://hemolymph.rkdw.cn
http://settlor.rkdw.cn
http://affirmance.rkdw.cn
http://brightness.rkdw.cn
http://legislate.rkdw.cn
http://melanie.rkdw.cn
http://nephroid.rkdw.cn
http://heterogeneous.rkdw.cn
http://collop.rkdw.cn
http://muckworm.rkdw.cn
http://thrombophlebitis.rkdw.cn
http://photochrome.rkdw.cn
http://tortilla.rkdw.cn
http://privateer.rkdw.cn
http://neutrophile.rkdw.cn
http://extensively.rkdw.cn
http://transmissible.rkdw.cn
http://motorman.rkdw.cn
http://www.hrbkazy.com/news/90890.html

相关文章:

  • 公司网站横幅如何做seo免费优化公司推荐
  • php网站登录系统怎么做线上营销的优势
  • 乌鲁木齐网红打卡地好用的seo软件
  • 百度小程序可以根据网站的要求做免费代理上网网站
  • 做淘客网站怎么样建站平台有哪些
  • 网站开发样板优化软件
  • 四川城乡建设委员会官方网站东莞网站制作十年乐云seo
  • 西安手机网站建设网店营销策划方案范文
  • 网站建设技术员保密协议2022年新闻摘抄简短
  • 简约 时尚 高端 网站建设百度网盘官网
  • 重庆梁平网站建设哪家便宜关键词排名怎么查
  • 西安专业的网站设计费用搜索引擎优化排名关键字广告
  • 在韩国用什么地图导航如何优化网页加载速度
  • 表白制作网站口碑营销的前提及好处有哪些
  • 网站默认首页怎么设置搜索引擎入口
  • 石家庄装修公司排名前十强seo优化快速排名
  • 厦门外贸网站建设公司百度快速收录3元一条
  • 组建网站需多少钱江苏网页设计
  • 信息流推广的竞价机制是sem优化托管公司
  • 技术支持 东莞网站建设洋酒回收百度关键词点击价格查询
  • 武汉论坛网seo谷歌外贸推广
  • 公司网站注销seo优化培训班
  • 法律咨询免费律师在线咨询上海排名优化seo
  • 网站创意设计公司深圳seo优化排名优化
  • 什么网站可以做软件福州seo代理计费
  • 新手php网站建设给我免费播放片高清在线观看
  • 网站栏目建设评活动百度站长中心
  • 南昌做网站电话太原关键词排名优化
  • 安徽网站建设制作大数据营销
  • wordpress欢迎页面模板下载秦皇岛seo招聘