如何写 go 代码 (How to Write Go Code 翻译)

目录

  • 1. 写在前面的话
  • 2. 介绍
  • 3. 代码组织
    • 3.1. 工作区
    • 3.2. GOPATH 环境变量
    • 3.3. Package 路径
    • 3.4. 第一个 GO 程序
    • 3.5. 第一个 GO 库
    • 3.6. Package name
  • 4. 测试
  • 5. 远程 package
  • 6. 下一步
  • 7. 获取帮助

写在前面的话

本文为Go官方网站 How to Write Go Code 这篇文章的翻译,
水平有限, 有些地方不好翻译的地方会用意译的方法, 关于代码示例的路径等方面可能也会有些不一样.

介绍

本文演示如何开发一个简单的 go package, 以及 go tool 的使用方法,
即获取, 编译, 安装 go package 的标准方法和命令.

go tool 需要你安装一定的标准来组织代码. 请仔细阅读本文.
它介绍了用来构建和运行 Go 程序的最简单方法.

介绍本文的视频参照: https://www.youtube.com/watch?v=XCsL89YtqCs (需要FQ!!!)

代码组织

工作区

go tool 是设计用来和公共仓库的开源代码一起工作的.
即使你不需要发布你的代码, go tool 的工作模型也同样适用于你.

Go 代码必须保存在 工作区 中, 工作区 就是一个特定的目录结构, 根目录下有如下3个目录:

  • src 目录: 存放 go 源码文件, 按 package 来组织 (一个 package 一个文件夹)
  • pkg 目录: 存放 package 对象
  • bin 目录: 存放可执行文件

go tool 编译 src 下的文件, 并将编译好的二进制文件分别放入 pkg 或者 bin 文件夹中.
src 目录可以包含多个 VC 仓库(比如 Git 或 Mercurial), 用来管理代码的开发.

下面是一个目录结构的示例:

├── bin                                   # 这里存放 可执行命令
├── pkg                                   # 这里存放 package 对象
│   └── darwin_amd64
│       ├── github.com
│       └── go-files
└── src├── github.com│   └── golang│       └── example│           ├── .git│           ├── hello               # 可执行命令的代码│           ├── outyet              # 可执行命令的代码│           └── stringutil          # package 代码└── go-files├── .git├── hello                        # 可执行命令的代码└── stringutil                   # package 代码

这里补充说明一下:
src 目录下:

  • github.com/golang/example 是 github 上的代码仓库
  • go-files 是本地的代码仓库

src 目录可以包含多个代码仓库, 可以包含多个命令的源码, 也可以包含多个 package 的源码.
大多数的 Go 程序员会将他们所有的 Go 源码和依赖关系保存在同一个工作区中.

可执行命令 和 库 是分别从不同的 package 的代码编译出来的, 稍后会讨论.

GOPATH 环境变量

GOPATH 环境变量定义了你的 工作区 的位置. 这是你开发 Go 代码时唯一需要设置的环境变量.

开始开发时, 创建 工作区 的文件夹, 并设置对应的 GOPATH 环境变量.
你的 工作区 可以是任意文件夹, 本文中使用的路径是 $HOME/go
注意 不要把 GOPATH 设置为 go 的安装路径.

$ mkdir $HOME/go
$ export GOPATH=$HOME/go

为了方便编译出的命令的执行, 将上面的 bin 目录加入到 PATH:

$ export PATH=$PATH:$GOPATH/bin

Package 路径

标准库中的 package 只要使用短路径即可, 比如 "fmt", "net/http".
对于自己的 package, 必须选一个基本的路径以防止以后和标准库, 或者其他第三方的库产生冲突.

如果你的代码保存在某个代码仓库, 那么就可以使用那个代码仓库的根目录作为你的 package 的基本路径.
比如, 你有个 github 的账户在 github.com/user, 就可以使用 github.com/user 作为你的基本路径.

注意 在能够正确编译代码之前, 你并不需要发布你的代码到远程的代码仓库.
但是如果有一天你会发布代码的话, 好好组织代码结构是个好习惯.
实际上, 你可以使用任意的路径名称, 只要它在 go 标准库和庞大的 go 生态系统中是唯一的.

我们使用 src/go-files 作为基本路径, 然后在工作区中创建文件夹来保存代码

$ mkdir -p $GOPATH/src/go-files

第一个 GO 程序

为了编译和运行一个简单的 GO 程序, 首先要确定 package 路径(这里使用 go-files/hello),
并且在工作区中创建对应 package 文件夹.

$ mkdir $GOPATH/src/go-files/hello

下一步, 在上面文件夹中创建 hello.go 文件, 文件内容如下:

package mainimport "fmt"func main() {fmt.Printf("Hello, world.\n")
}

然后, 可以通过 go tool 来编译和安装上面的 hello 程序.

$ go install go-files/hello

你可以在任何路径下运行上述命令, go tool 会根据 GOPATH 环境变量来从工作区中查找 go-files/hello package.

如果在 package 所在文件夹中运行 go install, 也可以省略 package 路径.

$ cd $GOPATH/src/go-files/hello
$ go install

上面的命令编译了 hello 命令, 并产生了此命令的二进制可执行文件.
然后将二进制文件 hello 安装到了 工作区 的 bin 文件夹下(Windows 下是 hello.exe)
在我们的例子中, 就是 $GOPATH/bin/hello, 即 $HOME/go/bin/hello

go tool 只有在出错时才会输出信息, 如果上面的 go 命令没有输出就说明执行成功了.
然后, 就可以在命令行中运行这个命令了.

$ $GOPATH/bin/hello

或者, 如果你将 $GOPATH/bin 加入到 PATH 中了的话, 也可以执行执行 hello 命令.

$ hello

如果你使用了代码版本管理工具, 这时就可以初始化你的仓库, 添加文件, 并 commit 你的第一个改变.
这个步骤是可选的, 写 go 代码并不强制要求使用代码版本管理工具.

$ cd $GOPATH/src/go-files/hello
$ git init
$ git add hello.go
$ git commit -m "initial commit"

发布这个仓库, 使之成为读者的练习仓库.

第一个 GO 库

让我们来写一个库, 并将之用于上面的 hello 程序中.
同样, 首先确定 package 路径 (这里使用 go-files/stringutil), 并创建对应的文件夹.

$ mkdir $GOPATH/src/go-files/stringutil

接着, 创建文件 reverse.go, 内容如下:

// Package stringutil contains utility functions for working with strings.package stringutil// Reverse returns its argument string reversed rune-wise left to right.func Reverse(s string) string {r := []rune(s)for i, j := 0, len(r)-1; i < len(r) / 2; i, j = i+1, j-1 {r[i], r[j] = r[j], r[i]}return string(r)}

用 go build 来编译此 package

$ go build go-files/stringutil

或者在 package 的目录下, 直接运行 go build

$ cd $GOPATH/src/go-files/stringutil
$ go build

上面的命令不会产生输出文件, 为了生成输出文件, 必须使用 go install 命令, 它会在 pkg 文件夹下生成 package 对象.
stringutil package 编译成功之后, 修改之前的 hello.go 文件:

package mainimport ("fmt""go-files/stringutil"
)func main() {fmt.Printf(stringutil.Reverse("!oG ,olleH"))
}

无论用 go tool 安装 package 对象还是 二进制文件, 它都会安装所有的依赖关系.
所以当你安装 hello 程序时,

$ go install go-files/hello

stringutil package 也会被自动安装.

运行新的 hello 程序, 可以看到如下输出:

$ hello
Hello, Go!

经过上面的步骤, 你的 工作区应该像下面这样:

bin/hello                 # command executable
pkg/darwin_amd64/          # this will reflect your OS and architecturego-files/stringutil.a  # package object
src/go-files/hello/hello.go      # command sourcestringutil/reverse.go    # package source

注意 go install 将 stringutil.a 放进了 pkg/darwin_amd64 文件夹下 和 代码对应的目录中.
以后, go tool 就可以找到这个 package, 从而判断是否需要重新编译.
darwin_amd64 是表示当前使用的系统, 它的目的是为了区分交叉编译出的其他平台的 package.

Go 编译出的二进制文件都是静态链接的, 所以上面的 bin/hello 在执行时并不需要 darwin_amd64/go-files/stringutil.a 文件.

Package name

go 代码的第一行必须是:

package name

这里的 name 作为 package 的默认名称, 让其他 package import 的时候用.(同个 package 中的所有文件必须使用相同的 name)
Go 的习惯是: package name 是 import path 中最后一部分.
也就是说, 如果一个 package 被引用时写成 "crypto/rot13", 那么这个 package 的 name 就是 rot13

编译为可执行文件的代码的 package name 必须是 main
一个二进制文件所关联的多个 package 的 name 不一定要唯一, 只要 pakage 的 import path 是唯一的就行.
也就是上面的 crypto/rot13 必须唯一, 但是可以有 another-crypto/rot13.

Go 的命名规则可以参考: http://golang.org/doc/effective_go.html#names

测试

Go 中包含一个轻量级的测试框架, 由 go test 命令和 testing package 组成.

测试文件的名称以 _test.go 结尾, 其中包含格式如 func TestXXXX(t *testing.T) 的函数.
测试框架会执行每个这样的函数, 如果函数中调用了 t.Error 或者 t.Fail, 就认为测试失败.

给上面的 package stringutil 增加测试文件, 路径: $GOPATH/src/go-files/stringutil/reverse_test.go, 内容如下:

package stringutilimport "testing"func TestReverse(t *testing.T) {cases := []struct {in, want string}{{"Hello, world", "dlrow ,olleH"},{"Hello, 世界", "界世 ,olleH"},{"", ""},}for _, c := range cases {got := Reverse(c.in)if got != c.want {t.Errorf("Reverse(%q) == %q, want %q", c.in, got, c.want)}}
}

执行测试的方法如下:

$ go test go-files/stringutil

或者进入到 package stringutil 的目录中后, 直接运行:

$ go test

通过 go help test 或者 http://golang.org/pkg/testing/ 来进一步 GO 的测试框架.

远程 package

Go 的 import path 可以描述如何从版本管理系统(Git 或者 Mercurial) 中获取 package 的源码.
go tool 可以利用这个特性来自动获取远程仓库的代码.
比如, 下面的例子中使用的代码同时也保存在 github 上(http://github.com/golang/example).

如果你在代码中 import 了上面这个远程的 package, 那么 go get 命令会自动 获取, 编译, 安装这个 package.

$ go get github.com/golang/example/hello
$ hello
Hello, Go examples!

如果本地没有指定 import 的 package, go get 命令会把这个 package 下载到 GOPATH 中定义的第一个工作区中.
(如果远程 package 不存在的话, go get 相当于 go install)

上面的 go get 命令执行之后, 文件夹结构大致如下:

├── bin
│   └── hello
├── pkg
│   └── darwin_amd64
│       ├── github.com
│       │   └── golang
│       │       └── example
│       │           └── stringutil.a
│       └── go-files
└── src├── github.com│   └── golang│       └── example│           ├── .git│           ├── hello│           │   └── hello.go│           └── stringutil│               ├── reverse.go│               └── reverse_test.go└── go-files├── hello│   └── hello.go└── stringutil├── reverse.go└── reverse_test.go

github.com 上的 hello 程序依赖同一个仓库中的 package stringutil,
即 github.com 上的 hello.go 中引用了 github.com 上的 package stringutil, 所以, go get 命令也下载, 编译, 安装了 stringutil 模块.

import ("fmt""github.com/golang/example/stringutil"
)

这个特性可以让你的 go package 很容易的被别人使用.
Go Wiki 和 godoc.org 上列出了很多第三方 Go 工程.
关于使用 go tool 来使用远程仓库的更多信息, 请参考: go help importpath

下一步

  • 订阅 golang-announce 邮件列表来了解最新的 Go release 信息
  • 将 Effective Go 作为参考资料来编写整洁, 地道的 Go 代码
  • 通过 A Tour of Go 来完成一次 go 的旅行
  • 访问 documentation page 来了解一系列关于Go语言的有深度的文章, 以及 Go 库和工具.

获取帮助

  • 寻求实时帮助, 可以使用 FreeNode 的IRC server #go-nuts
  • Go 语言官方邮件列表 Go Nuts
  • 汇报 Go 语言的 bug 请使用 Go issue tracker

转载于:https://www.cnblogs.com/wang_yb/p/4333331.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/263694.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Servlet规范定义的Servlet 生命周期

Servlet有良好的生存期的定义&#xff0c;包括如何加载、实例化、初始化、处理客户端请求以及如何被移除。这个生存期由javax.servlet.servlet接口的init,service和destroy方法表达。1、加载和实例化 容器负责加载和实例化一个Servlet。实例化和加载可以发生在引擎启动的时候&…

android auto 源代码,最近心血来潮,把Androidautosize的源码搂了一眼

https://codechina.csdn.net/mirrors/jessyancoding/androidautosize?utm_sourcecsdn_github_accelerator以上是Androidautosize的源码&#xff0c;有兴趣的就去下下来搂一眼我这边还没看完&#xff0c;就把最基础的看了一下&#xff0c;然后顺了下简单的流程&#xff0c;顺便…

11次作业

1、实验要求&#xff1a;建立一个通信录&#xff0c;通信录的结构体记录包括&#xff1a;姓名、生日、电话号码&#xff1b;其中生日又包括三项&#xff1a;年、月、日。编写程序&#xff0c;定义一个嵌套的结构类型&#xff0c;输入n&#xff08;n<10&#xff09;个联系人的…

Lucene.net 下载地址

Lucene.net 官方网站 http://lucene.apache.org/lucene.net/ Lucene.net 2.9.2 下载地址 Lucene.Net_2_9_2/ 转载于:https://www.cnblogs.com/leco/archive/2010/12/22/1913806.html

android内存卡测试,安卓sd卡真假检测工具_内存卡检测扩容卡软件_sd insight

内存卡检测扩容卡软件内存卡检测扩容卡软件由于U盘、TF卡&#xff0c;sd内存卡等移动存储设备越来越便宜&#xff0c;导致很在某宝上买到便宜且容量大的U盘或者内存卡&#xff0c;结果基本上都是扩容盘&#xff0c;所谓扩容盘&#xff0c;就是实际容量比如2G的U盘&#xff0c;经…

bashrcprofile

# /etc/bashrc# are we an interactive shell? 是交互式的shell吗&#xff1f;# System wide functions and aliases //系统功能和别名比如说&#xff1a;你设置个别名alias xixdate当你键入xix时&#xff0c;那么系统显示为命令date的信息。&#xff08;键入后才输出&#…

android ftp权限,实战android手机telnet、ftp登陆,权限修改

问题的提出&#xff1a;我用的手机是HTC magic&#xff0c;sd卡用的是金士顿的&#xff0c;不知道什么原因&#xff0c;总是有时能找到sd卡&#xff0c;有时找不到。我个人总有一些数据文件&#xff0c;想固定放在手机的系统上&#xff0c;而不是sd卡上(/sdcard)&#xff0c;那…

Linux nohup和的功效

Linux nohup和&的功效 https://www.cnblogs.com/laoyeye/p/9346330.html 这是我转载的文章&#xff0c;写的很好&#xff0c; nohup Command [ Arg ... ] [ & ] &&#xff1a;进程后台执行 不挂断地运行命令。no hangup的缩写&#xff0c;意即“不挂断” 例如&…

获取手机通讯录跟sim卡通讯录

/** 获取库Phone表字段 **/ private static final String[] PHONES_PROJECTION new String[] { Phone.DISPLAY_NAME, Phone.NUMBER }; private List<ContactsModel> contactsModels new ArrayList<ContactsModel>(); /** 得到手机通讯录联系人信息 **/ …

如何去掉ECShop 2.7.2中的Powered by ECShop字符

1.去掉标题上Powered by ECShop的字样如下: 在includes/lib_main.php找到lib_main.php文件,打开后,找到136行,将$page_title $GLOBALS[’_CFG’][’shop_title’] . ‘ – ‘ . ‘Powered by ECShop’ ;改为$page_title $GLOBALS[’_CFG’][’shop_title’] ;当然, . ‘ – ‘…

proguard android 配置,android – Proguard忽略库的配置文件

我现在面对一个非常奇怪的问题吗&#xff1f;我有一个具有两个模块的Gradle应用程序&#xff0c;一个主要模块和一个库模块。>在两个模块中&#xff0c;我已经声明了一个正确的proguard-rules.pro文件路径>在两个.gradle文件中我有minifyEnabled为true这是第一个问题&…

MySql Workbench 安全模式(safe mode)

默认情况下&#xff0c;MySql WorkBench 的安全模式是打开的&#xff0c;即&#xff1a;update、delete语句必须带 where 条件字句&#xff0c;单条记录更新或删除。 如果关闭安全模式&#xff08;safe mode&#xff09;&#xff1a; 菜单栏&#xff1a;编辑(Edit) ---> 个…

Hark的数据结构与算法练习之希尔排序

算法说明 希尔排序是插入排序的优化版。 插入排序的最坏时间复杂度是O(n2)&#xff0c;但如果要排序的数组是一个几乎有序的数列&#xff0c;那么会降低有效的减低时间复杂度。 希尔排序的目的就是通过一个increment&#xff08;增量&#xff09;来对数列分组进行交换排序&…

13 个超炫的 Conky 配置

Conky 是一款桌面美化及系统信息监控软件&#xff0c;有着很强的自定义性&#xff0c;如果你熟悉的话可以配置出各类不同效果的界面&#xff0c;而下面列出了 13 个超炫的 Conkey 配置&#xff0c;你可以尝试其中之一。 Bionic Conky&#xff1a; Hi-Tek Conky&#xff1a; Con…

android 播放声音 停止其他,Android AudioManager处理两个播放器同时有声音,停止其中一个播放的问题,暂停其他的播放...

尽管某个时刻只有一个activity可以运行&#xff0c;Android却是一个多任务环境&#xff0e;这对使用音频的应用带来了特殊的挑战&#xff0c;因为只有一个音频输出而可能多个媒体都想用它&#xff0e;在Android2.2之前&#xff0c;没有内建的机制来处理这个问题&#xff0c;所以…

数据仓库定义

数据仓库&#xff08;Data Warehouse&#xff09;是一个面向主题的&#xff08;Subject Oriented&#xff09;、集成的&#xff08;Integrated&#xff09;、相对稳定的&#xff08;Non-Volatile&#xff09;、反映历史变化&#xff08;Time Variant&#xff09;的数据集合&…

C# 操作 Word 修改word的高级属性中的自定义属性

为 Microsoft Word 创建自动化客户端 启动 Visual Studio .NET。在文件菜单上&#xff0c;单击新建&#xff0c;然后单击项目。从 Visual C# 项目类型中选择 Windows 应用程序。默认情况下会创建 Form1。添加对 Microsoft Word 对象库的引用。为此&#xff0c;请按照下列步骤操…

大型门户网站的可伸缩性架构设计

大型门户网站的可伸缩性架构设计2009-12-28 来源&#xff1a;网络我们知道&#xff0c;对于一个大型门户网站来说&#xff0c;可伸缩性是非常重要的&#xff0c;怎么样在纵向和横向有良好的可伸缩性&#xff0c;就需要在做架构设计的时候考虑到一个分的原则&#xff0c;我想在多…

html中dd dt的效果,html中dt dd

html中&#xff0c;dl,dt,dd怎么使用html中,dl和dd和dt标签是什么意思,什么时候需要用定义列表的意思 一般用在图文并排的时候 应网友提问。html中&#xff0c;dl和dd和dt标签是什么意思&#xff0c;什么时候需要html中&#xff0c;dl和dd和dt标签的意思如下&#xff1a;dl标签…