当你学会了越来越多的编程语言后,你就会发现,不同的语言的设计思路、用法习惯天差地别。为什么会有这么大的差别?这是一件很有趣的事情,今天我们就来聊聊。
值得一提的是,本文将会涉及很多种不同的语言,读者在看到自己熟练的语言时,会觉得非常简单,但看到自己不熟悉的语言时,看了这篇文章后,你又会觉得非常神奇。
当你学会了越来越多的编程语言后,你就会发现,不同的语言的设计思路、用法习惯天差地别。为什么会有这么大的差别?这是一件很有趣的事情,今天我们就来聊聊。
值得一提的是,本文将会涉及很多种不同的语言,读者在看到自己熟练的语言时,会觉得非常简单,但看到自己不熟悉的语言时,看了这篇文章后,你又会觉得非常神奇。
Go 语言对 JSON 中int类型的处理非常方便,基本涵盖了大多数特殊情况。
go fix ./...
这是 Go1.26 引入的一个新命令,用于进行一系列代码优化。它包含以下的一些功能:
proto.actor是一个跨语言的分布式Actor框架,支持多种编程语言,包括Go,也就是protoactor-go。虽然它提供了强大的功能,但在使用过程中也存在一些已知问题,这里列出来供参考。
我们在使用Go标准库以及一些第三方库时,经常看到需要传入一个context.Context类型的参数。Context 一词翻译过来叫做“上下文”,但在Go语言中,它到底有什么用,应该怎样用呢?
我们就以之前聊到的 五子棋AI 为例:
假设我们计算6步棋花了数秒钟,但是计算8步棋花了1分钟还没算出来,就可以提前返回计算6步的策略了。
这段话看似简单,实则涉及到并发编程的一个问题:提前返回后,8步棋的计算仍在进行,这样会持续浪费资源,如何将其停掉呢?
在Go语言中,尽管许多panic可以通过recover()函数来捕获并处理,但依然存在一些特定情况下引发的异常是无法被捕获的。本文将探讨几种常见的无法通过常规手段恢复的错误情形及其原因。
map当尝试同时从多个协程读取和修改同一个map时,如果没有适当的同步机制(如使用互斥锁),则会触发运行时错误。
m := make(map[int]int)
go func() { for { m[1] = 1 } }()
go func() { for { _ = m[1] } }()
select 语句从 Go 1.11 开始,Go 引入了模块化管理,并于 Go 1.16 版本开始正式成为默认构建模式。现在,Go 模块已经成为 Go 语言通用的包管理方式。
在项目根目录下使用go mod init example/mymodule就可以初始化一个 Go 模块,并生成一个名为 go.mod 的文件,其中第一行即为module example.com/mymodule。
go.mod 文件用于描述模块的依赖关系和版本信息。一个可能的 go.mod 文件可以包含以下内容:
整理了一下我用过的 Go 开源第三方库,供大家参考。使用时请注意遵守各个库的开源协议。
golangci-lint是一个Go语言的代码静态检查工具集,官网是https://golangci-lint.run/,它集成了多个流行的linters,可以帮助我们快速发现代码中的潜在问题。
一切的一切,要源于《冒险岛Online》在2018年推出的一个小游戏——名侦探甘迪:
游戏开始时,一群玩家会被传送进一个房间。此时,系统会在1-9九个数字中随机选择三个数字按某个顺序排列,作为答案。
每一轮,玩家需要按顺序猜测3个数字,系统会给出反馈,告知玩家有几个数字猜对了并且位置正确(用○表示),有几个数字猜对了但位置不正确(用△表示)。
举个例子:玩家猜测1-2-3三个数字,系统给出反馈1○1△,表示有一个数字猜对了并且位置正确,有一个数字猜对了但位置不正确。可能是1猜对了且位置正确,2猜对了但位置不正确,答案中没有3,当然也有别的可能。
玩家可以根据反馈来继续推测答案。所有玩家独立完成游戏,不能看到其它玩家的选择及反馈。玩家之间互为竞争对手,目标就是用最少的次数猜出答案。
问题就来了,如何设计策略,让我们在尽可能少的次数内猜出答案呢?
这是一个十分经典的策略问题。
pprof是Go语言的性能分析工具,可以帮助我们分析程序的性能瓶颈。pprof可以生成CPU、内存、阻塞等多种性能分析报告。
假如我们有一个Vue项目,希望将整个Vue项目的不同页面(通过路由访问的各个页面)导出,然后合并成一个PDF文件。为了解决这个问题,最容易的方法就是使用浏览器自带的保存页面功能。
如果我们要用程序来实现,实际上可以不需要真的有这么一个浏览器,确切说是不需要浏览器真的显示出来页面的内容,只需要它将页面加载好,供我们保存即可。于是就有了这样一个概念——无头浏览器。
在编写网络应用时,服务端与客户端的协议设计是一个非常重要的环节。本文将介绍业界常见的通信协议设计思路。
我们知道,对于面向对象编程(OOP),在程序的内存中,数据一般是struct、object等封装好的类型。而在网络上进行交互,却只能使用二进制流。因此就存在这样两个问题:
new函数增强new函数现在可以接受一个表达式来指定初始值。这在序列化包(如encoding/json和protobuf)中处理指针字段时尤为实用。
type Person struct {
Name string `json:"name"`
Age *int `json:"age"`
}
p := Person{
Name: "Alice",
Age: new(30), // 以前需要先声明一个变量再取地址
}
有这样一个问题:
给定一个3×3的网格,每个格子上有1-8共8个数字,最后一个格子是空的。每次只能将紧挨着空格子的一个格子移到空格子上,将其随机打乱,例如得到这样一个状态:
| 3 | 4 | |
|---|---|---|
| 5 | 2 | 8 |
| 1 | 6 | 7 |
现在请问,如何用尽可能少的步数将其恢复到初始状态?
在go run、go test、go build和go install命令中都可以使用-race参数来检测代码中的数据竞争风险。
go test -race test.go
go run -race main.go
go build -race -o main
go install -race mypkg
原文链接:The Go Memory Model (Version of June 6, 2022)
Go内存模型规定了在哪些条件下,可以保证一个goroutine对某个变量的读操作能够观察到另一个goroutine对该变量写入的值。
多个goroutine同时访问并修改数据时,必须将这些访问操作序列化。为了将访问操作序列化,应使用通道操作或其他同步原语(例如 sync 和 sync/atomic 包中提供的工具)来保护数据。
set GOOS=windows
set GOARCH=amd64
go build -ldflags "-s -w -H=windowsgui" -o test.exe