Golang实战中遇到适用场景选择的困惑,求开发者经验分享
Golang实战中遇到适用场景选择的困惑,求开发者经验分享 作为一名拥有多年PHP丰富经验的开发者,同时也熟悉Python以及HTML、JavaScript和CSS等其他Web技术,我发现与Kotlin/Java、C#和Node.JS相比,Go是一门极其迷人的语言(例如:大多数用例外部依赖少、跨平台编译、并发能力强)。然而,我仍然在努力寻找Go能真正满足我需求的实用场景。
在Web后端开发方面,PHP长期以来一直是我的首选语言。它不仅驱动着一些最大的CMS系统,而且PHP在7版本,尤其是8.3版本的改进中取得了长足进步,引入了即时编译器等功能。此外,PHP得到了大多数Web主机商的广泛支持,使其集成变得极其容易。无论是在共享虚拟主机、VPS还是专用云基础设施上运行,PHP都能动态扩展,轻松覆盖小型和大型用例。相比之下,部署基于Go的Web应用程序通常需要对服务器有更高级的访问权限,或者至少需要一个你能控制运行时环境的系统。一个简单的PHP脚本通常可以在基础的Web空间上运行,而Go则需要更定制的设置。
这并不是说我没有尝试过在不同的场景中使用Go。最近,我尝试用Go开发一个桌面应用程序,用于从PDF文件中提取文本,使用AI处理数据并进行分类。然而,我在Go提取PDF文本的能力方面遇到了重大挑战。尽管测试了几乎所有可用的库(例如GitHub - dslipak/pdf: PDF reader和GitHub - ledongthuc/pdf: PDF reader),但没有一个能处理我遇到的各种PDF文件。最终,我不得不依赖将Apache Tika Java应用程序与Go集成,这增加了不必要的复杂性,包括更大的文件大小以及需要在系统上安装Java。虽然这个解决方案可行,但我更希望有一个更直接、纯Go的方法。
从积极的一面来看,使用Go的Fyne框架构建桌面UI相对顺利且实用,所以那里肯定有潜力。然而,我最初的目标是构建一个功能齐全的、具有本地文件处理能力的Go桌面应用程序(为了最终用户的数据隐私,并且我可以免费向最终用户提供此程序),但这并不像我期望的那样无缝。
我发现Go不太实用的另一个领域是处理JSON结构。使用PHP和JavaScript处理JSON数据——尤其是在结构并非总是100%可预测的情况下,比如处理API响应时——感觉要容易得多。这两种语言在处理动态或部分定义的结构时都非常灵活。相比之下,在Go中处理JSON感觉有点更死板和繁琐,特别是当API响应并不总是完美匹配你预定义的结构时。我还注意到,当OpenAI引入新的结构化JSON格式时,Python库在Go库赶上之前几周就实现了对它的支持。这突显了在某些情况下,Go的生态系统可能会落后于Python或JavaScript等更成熟的语言。
在系统管理任务方面,我通常选择Python或Shell脚本。原因很简单:Python脚本通常内置了我所需的大部分功能,不需要额外的项目文件或复杂的设置。你只需编写脚本,运行它,它就能工作。此外,Python易于编辑且不需要编译,这对于日志文件分析、更新暂存系统等任务来说是完美的。在这里,Go的编译特性感觉不那么自然。我宁愿要一个简单、可编辑的脚本,不需要多个文件或复杂的构建过程。Go虽然强大,但对于这些快速、迭代的任务,它无法提供同样水平的简单性。
到目前为止,我已经在Web后端、桌面应用程序和系统管理脚本方面探索了Go,但我还没有找到一个案例能证明Go是更优越的选择。 无论是由于某些库的不成熟,还是语言的范式与某些任务不太匹配,我总是遇到限制。尽管我很兴奋地想更多地使用Go,但我经常发现对于我的大多数项目来说,PHP或Python最终是更实用的选择。
这就引出了我的问题:对于那些使用Go的人,你们主要构建的是什么样的应用程序? 如果你的用例与我的有重叠,我很想知道你为什么选择Go而不是PHP或Python。你的见解真的可以帮助我弄清楚Go在我的工作流程中最适合的位置,以及哪些项目可能会从中受益。
感谢分享你的想法!
更多关于Golang实战中遇到适用场景选择的困惑,求开发者经验分享的实战教程也可以访问 https://www.itying.com/category-94-b0.html
你可能会欣赏这些经验丰富的PHP开发者关于从PHP迁移到Go的(主要是)优点和(一些)缺点的看法。
更多关于Golang实战中遇到适用场景选择的困惑,求开发者经验分享的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
您知道Kubernetes是用Go语言开发的吗? 我认为Go语言非常适合后端开发,尤其是在微服务架构中。只需一个编译后的可执行文件结合Docker,就能非常轻松地实现持续集成/持续部署、自动扩缩容等操作。
几乎是为构建 RESTful API 量身定做的
在数据库之上构建 RESTful API,您会推荐什么框架呢?我认为 Go 几乎是编写服务器代码的最佳语言,只是我还没有找到任何 Go 框架能与 Python 的 FastAPI 相媲美。也许这个比较并不公平。
使用 FastAPI,你可以获得自动数据验证和强大的依赖注入系统。我确实发现了一些 Go 包,它们试图在 Go 中实现类似的功能(例如 GitHub - sashabaranov/go-fastapi: 创建 API 并免费获取 Swagger 定义),所以也许我需要在未来的项目中研究一下这些包。
为什么你选择 Go 而不是 PHP 或 Python
体积、依赖、速度。简而言之,它在各个方面都更经济。你可以使用 //embed 将网站构建为单个可执行文件。
虽然 Go 基本上不是为网页开发而设计的,但我发现 Go 的 HTML 模板非常容易创建我的第一个网站。尽管今天我应该用不同的方式来做这件事。
而且我还创建了一些 API 和 Cron 服务器,这些正是 Go 更擅长的领域。
你会推荐什么框架来在数据库之上构建 RESTful API?我认为 Go 几乎是编写服务器代码的最佳语言,只是我还没有找到任何能与 Python 的 FastAPI 相媲美的 Go 框架。也许这个比较不太公平。
实际上,你可以完全使用标准库来构建整个 REST API:json、net/http、sql/db 等。试试看。之后,去看看 ‘Gin 框架’。
- JSON 格式,在 Go 中处理 JSON,json 包,marshal,unmarshall: https://youtu.be/Vr63uGL7NrU?si=k6J0Fw6RazAg77Xg
- 结合 Docker 使用 database/sql 包: https://youtu.be/Y7a0sNKdoQk?si=O7C8qoD0ljWI1dPC
- net/http 包 -
Handle, HandleFunc, HandlerFunc, ListenAndServe ...https://youtu.be/5BIylxkudaE?si=_iK5dkAkZgtjbGOs https://youtu.be/H7tbjKFSg58?si=RneO7Qp77fCqFKTn - 使用 net/http 或其他第三方库在 Golang 中编写 API: https://youtu.be/npzXQSL4oWo?si=6AyHXq6Xb_buopTq
对于构建RESTful API,我尚未找到比Go更让我青睐的语言或生态系统。它几乎是为构建RESTful API量身定做的(标准库在这方面非常强大,无需任何外部依赖即可证明这一点)。并发处理简单且合乎逻辑。它有自己的设计哲学。交叉编译到不同目标平台比我用过的任何其他工具都更容易。其生态系统和工具链非常出色。
关于交叉编译,可以看看这个:
并听听Rob Pike在链接中的演讲。关于这一点,这里还有一些其他讨论:
https://www.reddit.com/r/golang/comments/1dqf2ng/whats_the_secret_of_the_go_compiler_and_why_dont/
根据我部署生产应用程序的实际经验,与其他语言构建的API相比,基于Go的API性能更好,也更容易理解。这对我所针对的云平台(主要是Google Cloud、AWS和Azure)很重要,因为这些平台的内存/CPU成本仍然较高,占用空间小至关重要。并且不止我一人这么认为:
除了能够快速迁移到更可靠的平台之外,我们在此期间还成功将基础设施成本削减了一半。
除此之外,我还用它来自动化重复性任务,因为我通常编写Go代码比编写bash脚本更快。另外,我团队中的一些开发人员不使用Linux,而bash脚本不具备跨平台性。
还有一点:在我使用过的所有Excel库中,excelize是最好的。因此,任何需要生成Excel报告的项目,如果我能做主,我都会使用Go。
目前我主要使用标准库,感觉非常高效。我的新项目大多使用Postgres作为数据库,并且我使用jackc/pgx,它在database/sql的基础上增加了批量导入、扫描到切片/结构体/结构体切片等功能。它还增加了一些Postgres独有的特性。
我不熟悉FastAPI,但你具体怀念它的哪些功能呢?我查看了他们的示例:
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
……在我看来,这与Go的代码并没有太大的不同:
package main
import (
"fmt"
"log"
"net/http"
)
func root(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `{"Hello": "World"}`)
}
func readItem(w http.ResponseWriter, r *http.Request) {
itemID := r.PathValue("item_id")
q := r.URL.Query().Get("q")
fmt.Fprintf(w, `{"item_id": %v, "q": "%v"}`, itemID, q)
}
func main() {
http.HandleFunc("GET /", root)
http.HandleFunc("GET /items/{item_id}", readItem)
log.Fatal(http.ListenAndServe(":8089", nil))
}
请注意,在实际应用中,你可能需要做一些清理或检查工作。但这两个例子都极其简化。
我尝试过使用Go开发桌面应用、Web服务、网络转发、监控服务、移动应用(混合)、OpenGL(2D)、树莓派4B开发等等。 我想我可以发表一些看法。
-
桌面应用 非常糟糕,目前没有太好的解决方案。我使用过Fyne并编写过应用程序,但其破坏性的API接口和奇怪的内存调度让我不喜欢这个开发框架,尽管它目前是纯Go中最好的GUI框架。 我也用过Wails,但它仍然缺少一些GUI功能,例如无法多窗口。
-
Web服务/网络 简单来说,Go在这方面有太多成功案例了,如果你对此有疑问,我认为你还没有深入了解。 最初,Golang在网络方面(Goroutine、Web库、CGO等)也具有巨大优势,这使得这门语言脱颖而出,其效率目前是毋庸置疑的。
-
工具库支持 由于成功案例和从业者比例的原因,Golang的非网络工具库相对薄弱,但这也没办法。 我也遇到过对PDF的支持,它是有缺陷的,因为大多数人并不关注这部分。
-
C语言 Golang的一大优势是非常接近C语言,当你需要引用一些C库时相对容易。 由于类似的原因,有很多C绑定库,你通常可以通过查看C文档来编写相应的Go代码,例如OpenGL、Qt、VLC等。
-
嵌入式 不可否认,用它来写嵌入式项目确实有用,但相对小众,所以我这里不做评论。
-
总结 没有哪种开发语言是完美的,Golang也不例外。但它高效且易用,如果你想知道能用Golang做什么,你应该看看别人在做什么(比如GitHub上知名的Go项目)。
-
题外话 由于Golang的简单设计,开发者很容易写出奇怪的代码,至少在我的观察中是这样。 也可能是因为这个原因,他们更喜欢语法糖更高或库集成度更高的语言。
Go在并发密集型、网络服务和基础设施工具方面确实表现出色。以下是一些具体的应用场景和示例:
1. 高并发Web服务 Go的goroutine和channel机制非常适合处理大量并发连接,比如API网关、实时聊天服务:
package main
import (
"net/http"
"time"
)
func handler(w http.ResponseWriter, r *http.Request) {
time.Sleep(100 * time.Millisecond) // 模拟处理耗时
w.Write([]byte("请求处理完成"))
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
2. 微服务架构 Go编译为单个二进制文件,部署简单,适合微服务:
// user-service/main.go
package main
import (
"encoding/json"
"net/http"
)
type User struct {
ID int `json:"id"`
Name string `json:"name"`
}
func main() {
http.HandleFunc("/users/1", func(w http.ResponseWriter, r *http.Request) {
user := User{ID: 1, Name: "张三"}
json.NewEncoder(w).Encode(user)
})
http.ListenAndServe(":3001", nil)
}
3. CLI工具 Go的交叉编译能力使其成为CLI工具的理想选择:
package main
import (
"flag"
"fmt"
"os"
)
func main() {
file := flag.String("f", "", "要处理的文件")
flag.Parse()
if *file == "" {
fmt.Println("请指定文件路径")
os.Exit(1)
}
content, err := os.ReadFile(*file)
if err != nil {
fmt.Printf("读取文件失败: %v\n", err)
os.Exit(1)
}
fmt.Printf("文件大小: %d 字节\n", len(content))
}
4. 数据处理管道 利用channel构建高效的数据处理流水线:
package main
import (
"fmt"
"time"
)
func producer(ch chan<- int) {
for i := 0; i < 10; i++ {
ch <- i
time.Sleep(50 * time.Millisecond)
}
close(ch)
}
func worker(id int, ch <-chan int, results chan<- string) {
for num := range ch {
results <- fmt.Sprintf("Worker %d 处理了: %d", id, num*2)
time.Sleep(100 * time.Millisecond)
}
}
func main() {
dataCh := make(chan int, 5)
resultsCh := make(chan string, 10)
go producer(dataCh)
// 启动3个worker
for i := 1; i <= 3; i++ {
go worker(i, dataCh, resultsCh)
}
for i := 0; i < 10; i++ {
fmt.Println(<-resultsCh)
}
}
5. JSON处理示例 Go的JSON处理虽然需要结构体,但可以通过灵活的方式处理动态数据:
package main
import (
"encoding/json"
"fmt"
)
func main() {
// 动态JSON处理
jsonData := `{"name": "John", "age": 30, "extra": {"city": "NYC"}}`
var data map[string]interface{}
json.Unmarshal([]byte(jsonData), &data)
// 安全访问嵌套字段
if extra, ok := data["extra"].(map[string]interface{}); ok {
if city, ok := extra["city"].(string); ok {
fmt.Printf("城市: %s\n", city)
}
}
// 使用结构体标签处理不同字段名
type User struct {
Name string `json:"name"`
Age int `json:"age"`
}
var user User
json.Unmarshal([]byte(jsonData), &user)
fmt.Printf("用户: %s, 年龄: %d\n", user.Name, user.Age)
}
6. HTTP客户端并发请求
package main
import (
"fmt"
"io"
"net/http"
"sync"
)
func fetchURL(url string, wg *sync.WaitGroup) {
defer wg.Done()
resp, err := http.Get(url)
if err != nil {
fmt.Printf("获取 %s 失败: %v\n", url, err)
return
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
fmt.Printf("%s: %d 字节\n", url, len(body))
}
func main() {
urls := []string{
"https://api.github.com",
"https://httpbin.org/get",
"https://jsonplaceholder.typicode.com/posts/1",
}
var wg sync.WaitGroup
for _, url := range urls {
wg.Add(1)
go fetchURL(url, &wg)
}
wg.Wait()
}
Go在以下场景中特别有优势:
- 需要高并发处理的网络服务
- 需要快速启动和低内存占用的服务
- 需要部署简单的CLI工具
- 微服务架构中的各个服务组件
- 需要精确控制并发和资源使用的场景
对于PDF处理这类特定领域,Go的生态确实可能不如Python成熟。但在网络编程、并发处理和系统工具开发方面,Go提供了PHP和Python难以比拟的性能和部署优势。

