09|即学即练:构建一个Web服务就是这么简单
09|即学即练:构建一个Web服务就是这么简单
讲述:Tony Bai
时长20:05大小18.35M
预热:最简单的 HTTP 服务
图书管理 API 服务
项目建立与布局设计
项目 main 包
图书数据存储模块(store)
HTTP 服务模块(server)
编译、运行与验证
小结
思考题
资源链接
赞 47
提建议
精选留言(78)
- 自由2021-11-05Tony Bai 老师的这篇“简单”的 Web 代码构建,细节特别多,足矣看出功力深厚。例如锁的选型、工程化、为什么用锁、面向接口、设计模式、通过 Channel 通信而不是共享内存、panic 和 error 的区别。我认为这样的代码,是一个完美的开始。共 5 条评论42
- 扣剑书生2021-11-30store.go提供了 图书 和 接口的模板 factory 用于生产 接口实例 memstore.go 用于具体实现一个接口实例,实现其方法,并把样例发送到工厂 server.go 用于把路由和接口的方法对接起来
作者回复: 👍
19 - 尧九之阳2021-11-10Go现在有流行的web服务器框架么?
作者回复: go最初有很多web框架,经过多年演进,目前gin这个web框架似乎成为了go社区的首选。
共 2 条评论8 - 布凡2021-11-04终于实验成功: 以下几个点需注意: 1、项目应放到 gopath货goroot相关的目录下,否则本地包的引用会报错,报错信息如下:"could not import errors (cannot find package "errors" in any of c:\go\src\errors (from $GOROOT)...)" 2、如果是复制的代码应该注意文件格式,可能报错"package main: read unexpected NUL in input"展开
作者回复: 项目都是在mac/linux上做的。但理论上windows可以直接使用。你提到的项目放在gopath或goroot下是不必要的。支持go module模式后,如果启用了go module构建模式,放在哪个目录下都是可以的。 另外项目代码放在了github上,在文章末尾有链接。可直接clone后使用。
共 4 条评论7 - 猫饼2021-11-02我果然还是太菜了 我开始看不懂了
作者回复: 先“照猫画虎”吧。一旦涉及此类实战小项目,必然会有没有系统学习的内容。后面学习新语法时,可以回过头来复习。
共 2 条评论7 - 高雪斌2021-11-01C++转Go, Go语言设计的确实很简洁、精妙。Tony Bai老师从语言结构开始讲的风格非常受用,比通常的从语法开始讲的形式要好,虽然一些代码现在看不明白,但这样带着问题学习语法更容易理解。5
- 顷2022-02-21老师的这个示例,麻雀虽小,五脏俱全。不过main.go里有一点疑问:http.Server.Shutdown(ctx)被调用后,http.Server.ListenAndServe()方法马上会返回error吧,按照实例代码里的写法,接收到中断信号后,马上调用Shutdown方法,此时errChan会返回ErrServerClosed,select逻辑走完,main方法就退出了,而go的http包里示意了我们需要确保shutdown调用后,整个代码不能马上退出,请老师解惑。。
作者回复: 好问题! 首先errChan并不是等shutdown之后 listenAndServe报错的。而是等运行国产中,listenandserve一旦报错,程序可以退出。 接下来,我们再说说优雅退出。按照你的描述,我翻了一下net.http的文档: “Shutdown gracefully shuts down the server without interrupting any active connections. Shutdown works by first closing all open listeners, then closing all idle connections, and then waiting indefinitely for connections to return to idle and then shut down. If the provided context expires before the shutdown is complete, Shutdown returns the context's error, otherwise it returns any error returned from closing the Server's underlying Listener(s).” 我的理解是调用Shutdown后,ListenAndServe()方法的确会马上返回,不过这个无所谓了,listenandserver只是将listen端口关闭,不接受新连接了。 真正等待存量连接处理完毕的是shutdown方法,shutdown方法调用后,不是马上退出的哦。shutdown方法有一个ctx,专栏中传入了一个timeout ctx,时间为1s。即等待1s。关键就在这里。在生产环境,我们可能不能无限期等待程序退出,我们会设置一个timeout。如果shutdown在1s内完成等待,成功退出,这是最理想的。如果shutdown没有在1s内完成等待,即存量连接还没有处理完,那么按照我们的约定,我们也不能再等了。 当然这里只是demo,使用的timeout=1s。在生产中,你可以根据业务的类型以及经验值来等待。甚至可以进行无限等待,这完全取决于你的系统。
共 2 条评论4 - lesserror2021-11-02感谢 Tony Bai 老师这样由浅入深,并且尽可能贴近实战的讲解。 有以下困惑,麻烦解忧。 1. 对于一个module中,相同的包名,go内部是根据文件位置的不同,加以区分的吧? 例如:bookstore/store 和 bookstore/internal/store 这两个 package 同名,但是文件的路径不同,所以并不会有什么问题。如果在同一个package中,导入另一个同名的package,最佳实践是取个别名,我的理解没错吧? 2. 另外在 memstore.go 中的 包导入语句中: factory "bookstore/store/factory",这个 默认使用的是factory名字,不需要再另起名字为factory吧? 3. 这门课中的知识和你在另外的一个平台的《改善Go语言编程质量的50个有效实践》的内容重合度大吗? 精力有限,如果重合度大,就专心看这个就好了。 4. 这门课会讲讲Go写RPC服务方面的知识吗? 这个在生产中挺常用的。展开
作者回复: 问题1. 你的理解没有错。 问题2. 可以不用另起,记得好像有些工具在格式化时会自动填上。 3. 定位不同,这个是入门专栏。那个进阶专栏。有很小部分有相似的地方,但讲解方式都做了调整和优化。建议学完这个专栏后,再去看看那个专栏。 4. rpc封装的很深,如果仅是使用的话,没啥东西。这个专栏更多聚焦于go语法以及尽量使用标准库的东西做一些实用程序和项目。
共 5 条评论4 - return2021-11-01老师讲的太赞了 市面上 讲 go 接口思想很好, 推荐组合思想。 但是都光说不练,看懂但学不会。 今天老师 给的这个例子 真实,简短 且 把接口和组合的 思想都 做了出来, 太牛了。 这一篇 需要实践而且需要反复揣摩。共 2 条评论4
- includestdio.h2022-03-28作为基本0基础学go,这一节完全没看懂-,- 把后面的基础篇看完回来再试试吧
作者回复: 这一讲开头我就说了:“在这个小项目里,我希望你不要困在各种语法里,而是先跟着我““照猫画虎”地写一遍、跑一次,感受 Go 项目的结构,体会 Go 语言的魅力。” 😁 不用担心,往后学一学之后再来复习。
共 2 条评论3 - 小明2022-03-20能在gitee 上也放一份吗?github现在已经没那么友好了
作者回复: good idea。已创建https://gitee.com/bigwhite/publication/tree/master/column/timegeek/go-first-course 供下载。
共 3 条评论3 - 左耳朵东2021-12-03server/server.go 文件中 select 那里,第二个 case 的意思是定时 1 秒后就会触发,从而执行后面的 return,为什么服务没有终止一直在运行呢?麻烦老师解答一下
作者回复: 你说的是func (bs *BookStoreServer) ListenAndServe这个方法吧?这个函数等待1s后返回啊。但它启动的子goroutine依旧在运行的。子goroutine中bs.srv.ListenAndServe一直在工作,并提供服务。
共 3 条评论3 - jc9090kkk2021-11-01这节课的项目内容理解起来不困难,但是对于实际的生产项目而言,尤其是对第三方的中间件有依赖的前提下,大都会针对的将配置单独存储为配置文件以方便维护,我想问下老师go项目针对配置文件有什么最佳实践方式吗? 我自己本地写了一个小项目,用的是以下方式来配置MySQL连接的,我总觉得不太优雅,大多项目会根据开发环境的不同选取不同的配置文件作为配置项加载,但是如果通过硬编码的方式添加进去会让项目变得很奇怪。。。 package config // GetDBConfig 数据库配置 func GetDBConfig() map[string]string { // 初始化数据库配置map dbConfig := make(map[string]string) dbConfig["DB_HOST"] = "127.0.0.1" dbConfig["DB_PORT"] = "3306" dbConfig["DB_NAME"] = "test" dbConfig["DB_USER"] = "root" dbConfig["DB_PWD"] = "123456" dbConfig["DB_CHARSET"] = "utf8" // 连接池最大连接数 dbConfig["DB_MAX_OPEN_CONNECTS"] = "20" // 连接池最大空闲数 dbConfig["DB_MAX_IDLE_CONNECTS"] = "10" // 连接池链接最长生命周期 dbConfig["DB_MAX_LIFETIME_CONNECTS"] = "7200" return dbConfig }展开
作者回复: 生产项目一般不会将配置“硬编码”进去的。一般而言,配置项会存储在配置文件中,也有通过命令行参数传入程序的,也可以通过环境变量传入程序。Go标准库没有内置配置读写框架,目前go社区应用较多的第三方库是Go核心团队成员开发的viper(github.com/spf13/viper)。 对于一些更大的平台,常常有很多服务,这些服务的配置一般存储在专门的配置中心中,由配置中心管理与分发。
共 5 条评论3 - 莫名四下里2021-11-25Tony Bai 老师 $ go build bookstore/cmd/bookstore/ package bookstore/cmd/bookstore is not in GOROOT (/usr/local/go/src/bookstore/cmd/bookstore) 无法构建 配置 GOROOT="/usr/local/go" 报错 /usr/local/go/src/bookstore/cmd/bookstore展开
作者回复: 进入bookstore目录,go build ./cmd/bookstore或go build bookstore/cmd/bookstore
共 3 条评论2 - snow2021-11-05我看这里使用了mux包,我只用过gin包,请问这两个老师更喜欢哪个?以及这里选择mux的原因。
作者回复: 原则就是如果标准库中的mux可以满足,尽量不引用第三方包。如果标准库无法满足,尽量引用规模较小的包。gin是更大的web框架。除了mux,还有很多其他功能。如果不是项目必需,使用更“专一”的包可能更好。
3 - 邰洋一2021-11-05老师,采用Restful规范,更新一条图书条目 http方法采用PUT,当然post也是可以的,put book/id,是我太限定自己了吗?
作者回复: 你的建议很好。不过一个例子而已,别太计较:)
共 2 条评论2 - 小明2022-07-28 来自陕西看了两遍代码,能跑起来,但是只吃透了百分之三十,好着急啊 memstore.go 没看懂
作者回复: 很正常,这个例子并非让你完全理解,学到第09讲要是完全理解了,那后面就不用学习了:)
1 - Geek_zkg2022-05-18我是mac环境,按照老师上面的步骤走下来,在go build bookstore/cmd/bookstore的时候 报错package bookstore/cmd/bookstore is not in GOROOT (/usr/local/go/src/bookstore/cmd/bookstore) 我已经设置了GO111MODULE="on" 用goland开发的 想请老师帮忙解决一下展开
作者回复: 问一下,你的goland版本是?是否支持go module编译?GO111MODULE="on"对于goland是否生效了?
1 - FECoding2022-03-23providersMu.RLock() 我的goland里面报错啊,没有这个方法呢
作者回复: 方法肯定是有的啊。 $go doc sync.RWMutex.RLock package sync // import "sync" func (rw *RWMutex) RLock() RLock locks rw for reading. It should not be used for recursive read locking; a blocked Lock call excludes new readers from acquiring the lock. See the documentation on the RWMutex type.
1 - 6010738912022-03-17大大你好,这次遇到这样一个问题: 这次的代码在linux下能成功的运行,但是在window下虽然能成功构建出可执行文件,也能成功执行, D:\Goproject\src\entity\class\bookstore\cmd\bookstore>bookstore.exe 2022/03/17 23:10:49 web server start ok 但在本机通过curl 访问时却有这样一个报错: C:\Users\user>curl -X POST -H "Content-Type:application/json" -d '{"id": "978-7-111-55842-2", "name": "The Go Programming Language", "authors":["Alan A.A.Donovan", "Brian W. Kergnighan"],"press": "Pearson Education"}' 192.168.1.7:8080/book curl: (6) Could not resolve host: 978-7-111-55842-2, curl: (3) URL using bad/illegal format or missing URL curl: (3) URL using bad/illegal format or missing URL curl: (3) bad range in URL position 10: authors:[Alan A.A.Donovan, 不同系统下的go版本都是1.17,全部默认使用go module,我百度了一下,有说是URL格式的问题,但没有很对应,看了评论您也在windows上能成功执行,所以有这个疑问,您知道这会是怎么回事吗?展开
作者回复: 是不是命令行curl中的单引号、双引号的全半角问题导致的呢?
共 2 条评论1