golang基础之工程结构
Golang 工作空间
编译工具对源码目录有严格要求,每个工作空间 (workspace) 必须由 bin、pkg、src 三个目录组成。
workspace
|
+--- bin // go install 安装目录。
| |
| +--- learn
|
+--- pkg。 // go build 生成静态库 (.a) 存放目录。
| |
| +--- darwin_amd64
| |
| +--- mylib.a
| |
| +--- mylib
| |
| +--- sublib.a
|
+--- src // 项目源码目录。
|
+--- learn
| |
| +--- main.go
|
+--- mylib
|
+--- mylib.go
|
+--- sublib
|
+--- sublib.go
可在 GOPATH
环境变量列表中添加多个工作空间,但不能和 GOROOT
相同。
export GOPATH=$HOME/projects/golib:$HOME/projects/go
通常 go get
使用第一个工作空间保存下载的第三方库。
Golang目前有很多很多个标准的包,覆盖了几乎所有的基础库。
golang.org有所有包的文档。
Golang 源文件
编码:源码文件必须是 UTF-8
格式,否则会导致编译器出错。
结束:语句以 ";"
结束,多数时候可以省略。
注释: 持 "//"、"/**/"
两种注释方式,不能嵌套。
命名:采用 camelCasing
风格(驼峰命名法),不建议使用下划线。
Golang 包结构
所有代码都必须组织在 package 中。
• 源文件头部以 "package <name>" 声明包名称。
• 包由同一目录下的多个源码文件组成。
• 包名类似 namespace,与包所在目录名、编译文件名无关。
• 目录名最好不用 main、all、std 这三个保留名称。
• 可执行文件必须包含 package main,入口函数 main。
说明:os.Args 返回命令行参数,os.Exit 终止进程。要获取正确的可执行文件路径,可用 filepath.Abs(exec.LookPath(os.Args[0]))
。
package 基本的管理单元:
同一个package下面,可以有非常多的不同文件,只要每个文件的头部 都有 如 "package xxx" 的相同name
就可以 在主方法中使用 xxx.Method()调用不同文件中的方法了。
文件夹名字可以和这个package 名称不一致,
比如我有个文件夹名字是mypackage,其中包含了a.go,b.go, c.go三个文件 :
mypackage
| --a.go
| --b.go
| --c.go
比如a.go中有 Saya(),b.go中有Sayb() 而几个文件共同的package name 确是testpackage
所以在 主函数中调用a.go 和b.go文件中的各自方法只要用,testpackage.Saya() ,testpackage.Sayb()即可
还有默认的init方法,在import进来的时候就去执行了,而且允许每个文件中都有init()这个方法,当然是每个都会执行。
导出包:
在 Go 中,包中成员以名称首字母大小写决定访问权限。首字母大写的名称是被导出的。
在导入包之后,你只能访问包所导出的名字,任何未导出的名字是不能被包外的代码访问的。
Foo 和 FOO 都是被导出的名称。名称 foo 是不会被导出的。
• public: 首字母大写,可被包外访问。
• internal: 首字母小写,仅包内成员可以访问。
该规则适用于全局变量、全局常量、类型、结构字段、函数、方法等。
导入包 :使用包成员前,必须先用 import 关键字导入,但不能形成导入循环。
import "相对目录/包主文件名"
相对目录是指从<workspace>/pkg/<os_arch>
开始的子目录,以标准库为例:
import "fmt" -> /usr/local/go/pkg/darwin_amd64/fmt.a
import "os/exec" -> /usr/local/go/pkg/darwin_amd64/os/exec.a
在导入时,可指定包成员访问方式。比如对包重命名,以避免同名冲突。
import 用法:
import "fmt" 最常用的一种形式(系统包)
import "./test" 导入同一目录下test包中的内容(相对路径)
import "shorturl/model 加载gopath/src/shorturl/model模块(绝对路径)
import f "fmt" 导入fmt,并给他启别名f
import . "fmt" 将fmt启用别名".",这样就可以直接使用其内容,而不用再添加fmt。
如fmt.Println可以直接写成Println
import _ "fmt" 表示不使用该包,而是只是使用该包的init函数,并不显示的使用该包的其他内容。
注意:这种形式的import,当import时就执行了fmt包中的init函数,而不能够使用该包的其他函数。
未使用的导入包,会被编译器视为错误 (不包括 "import _"
)。
./main.go:4: imported and not used: "fmt"
自定义路径 :可通过 meta 设置为代码库设置自定义路径。
server.go
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, `<meta name="go-import"
content="test.com/qyuhen/test git https://github.com/qyuhen/test">`)
}
func main() {
http.HandleFunc("/qyuhen/test", handler)
http.ListenAndServe(":80", nil)
}
该示例使用自定义域名 test.com 重定向到 github。
$ go get -v test.com/qyuhen/test
Fetching https://test.com/qyuhen/test?go-get=1
https fetch failed.
Fetching http://test.com/qyuhen/test?go-get=1
Parsing meta tags from http://test.com/qyuhen/test?go-get=1 (status code 200)
get "test.com/qyuhen/test": found meta tag http://test.com/qyuhen/test?go-get=1
test.com/qyuhen/test (download)
test.com/qyuhen/test
如此,该库就有两个有效导入路径,可能会导致存储两个本地副本。为此,可以给库添加专门的 "import comment"。当 go get 下载完成后,会检查本地存储路径和该注释是否一致。
github.com/qyuhen/test/abc.go
package test // import "test.com/qyuhen/test"
func Hello() {
println("Hello, Custom import path!")
}
如继续用 github 路径,会导致 go build 失败。
$ go get -v github.com/qyuhen/test
github.com/qyuhen/test (download)
package github.com/qyuhen/test
imports github.com/qyuhen/test
imports github.com/qyuhen/test: expects import "test.com/qyuhen/test"
这就强制包用户使用唯一路径,也便于日后将包迁移到其他位置。
Golang初始化
初始化函数:
• 每个源文件都可以定义一个或多个初始化函数。
• 编译器不保证多个初始化函数执行次序。
• 初始化函数在单一线程被调 ,仅执行一次。
• 初始化函数在包所有全局变量初始化后执行。
• 在所有初始化函数结束后才执行 main.main()。
• 无法调用初始化函数。
因为无法保证初始化函数执行顺序,因此全局变量应该直接用 var 初始化。
var now = time.Now()
func init() {
fmt.Printf("now: %v\n", now)
}
func init() {
fmt.Printf("since: %v\n", time.Now().Sub(now))
}
可在初始化函数中使用 goroutine,可等待其结束。
var now = time.Now()
func main() {
fmt.Println("main:", int(time.Now().Sub(now).Seconds()))
}
func init() {
fmt.Println("init:", int(time.Now().Sub(now).Seconds()))
w := make(chan bool)
go func() {
time.Sleep(time.Second * 3)
w <- true
}()
<-w
}
输出:
init: 0
main: 3
不应该滥用初始化函数,仅适合完成当前文件中的相关环境设置。
Golang 文档
扩展工具 godoc 能自动提取注释生成帮助文档。
• 仅和成员相邻 (中间没有空行) 的注释被当做帮助信息。
• 相邻行会合并成同一段落,用空行分隔段落。
• 缩进表示格式化文本,比如示例代码。
• 自动转换 URL 为链接。
• 自动合并多个源码文件中的 package 文档。
• 无法显式 package main 中的成员文档。
Package
• 建议用专门的 doc.go 保存 package 帮助信息。
• 包文档第一整句 (中英文句号结束) 被当做 packages 列表说明。
Example
只要 Example 测试函数名称符合以下规范即可。
格式 | 示例 | |
---|---|---|
package | Example, Example_suffix | Example_test |
func | ExampleF, ExampleF_suffix | ExampleHello |
type | ExampleT, ExampleT_suffix | ExampleUser, ExampleUser_copy |
method | ExampleT_M, ExampleT_M_suffix | ExampleUser_ToString |
说明:使用 suffix 作为示例名称,其首字母必须小写。如果文件中仅有一个 Example 函数,且调用了该文件中的其他成员,那么示例会显示整个文件内容,而不仅仅是测试函数自己。
Bug
非测试源码文件中以 BUG(author) 开始的注释,会在帮助文档 Bugs 节点中显示。
// BUG(yuhen): memory leak.
欢迎您关注程序员同行者订阅号,程序员同行者是一个技术分享平台,主要是运维自动化开发:linux、python、django、saltstack、redis、golang、docker、kubernetes、vue等经验分享及经验交流。
趁现在,关注我们
牛人并不可怕,可怕的是牛人比我们还努力!
如果您觉得不错,请别忘了转发、分享、点赞让更多的人去学习, 您的举手之劳,就是对小编最好的支持,非常感谢!
golang基础之工程结构的更多相关文章
- golang基础知识之encoding/json package
golang基础知识之json 简介 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式.可以去json.org 查看json标准的清晰定义.json pack ...
- Golang基础之函数
golang基础之函数 1.为什么需要函数? 有些相同的代码可能出现多次,如果不进行封装,那么多次写入到程序中,会造成程序冗余,并且可读性降低 2.什么是函数 为完成某些特定功能的程序指令集合称为函数 ...
- GoLang基础数据类型--->字典(map)详解
GoLang基础数据类型--->字典(map)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 可能大家刚刚接触Golang的小伙伴都会跟我一样,这个map是干嘛的,是 ...
- GoLang基础数据类型-切片(slice)详解
GoLang基础数据类型-切片(slice)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 数组的长度在定义之后无法再次修改:数组是值类型,每次传递都将产生一份副本.显然这种数 ...
- GoLang基础数据类型--->数组(array)详解
GoLang基础数据类型--->数组(array)详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Golang数组简介 数组是Go语言编程中最常用的数据结构之一.顾名 ...
- GoLang基础数据类型--->字符串处理大全
GoLang基础数据类型--->字符串处理大全 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 欢迎加入: 高级运维工程师之路 59843264 ...
- 如何使用gitlab自建golang基础库
这里以go mod方式建立golang基础库 一.gitlab创建项目golib 地址为gitlab.xxx.com/base/golib 示例如下 go mod初始化命令 go mod init g ...
- Golang 基础之基础语法梳理 (三)
大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第三章节 Golang 基础之基础语法梳理 (一) Gol ...
- Golang 基础之基础语法梳理 (一)
大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第一章节 Golang 基础之基础语法梳理 (一) Gol ...
随机推荐
- IT兄弟连 HTML5教程 HTML5的基本语法 了解HTML及运行原理
了解HTML HTML(HyperText Marked Language)即超文本标记语言,是一种用来制作超文本文档的简单标记语言.我们在浏览网页时看到的一些丰富的影像.文字.图片等内容都是通过HT ...
- Flink on Yarn的两种模式及HA
转自:https://blog.csdn.net/a_drjiaoda/article/details/88203323 Flink on Yarn模式部署始末:Flink的Standalone和on ...
- javascript实现base64编码、解码
我们知道,浏览器的window对象提供有window.atob()和window.btoa()方法可以对字符串进行Base64编码和解码. console.log(window.btoa(window ...
- vscode打开文件在同一个tab的问题
当我们单击或者 cmd+鼠标左键单击打开文件时,有时候是在同一个窗口,有时候是新的窗口,这是啥样呢? 这是因为vscode有 "预览模式" , 当是预览模式时,打开的是当前窗口 ...
- 利用Python突破验证码限制
一.实验说明 本实验将通过一个简单的例子来讲解破解验证码的原理,将学习和实践以下知识点: Python基本知识 PIL模块的使用 二.实验内容 安装 pillow(PIL)库: $ sudo apt- ...
- Java三大性质总结:原子性、可见性以及有序性
本人免费整理了Java高级资料,涵盖了Java.Redis.MongoDB.MySQL.Zookeeper.Spring Cloud.Dubbo高并发分布式等教程,一共30G,需要自己领取.传送门:h ...
- swoole 内存泄露的问题有没有好的办法解决
在传统的web开发模式中,我们知道,每一次php请求,都要经过php文件从磁盘上读取.初始化.词法解析.语法解析.编译等过程,而且还要与nginx或者apache通信,如果再涉及数据库的交互,还要再 ...
- Node.js提供了哪些内容(API)
Nodejs运行时,JavaScript代码运行时的环境. 提供了一些核心模块,应用程序编程接口(Application Program Interface,API) API 的意思就是.一个已经解 ...
- E203数据冲突处理OITF
流水线的数据冲突分为三类:WAR,RAW,WAW https://wenku.baidu.com/view/e066926d48d7c1c708a14508.html WAR: write after ...
- 一文解读CQRS (转)
先从CQRS说起,CQRS的全称是Command Query Responsibility Segregation,翻译成中文叫作命令查询职责分离.从字面上就能看出,这个模式要求开发者按照方法的职责是 ...