文章转自:bboyHan (文末有彩蛋)
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。
Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。
Go作为一种简便灵巧的语言,深受开发者的喜爱。但对于初学者来说,要想轻松驾驭它,还得做好细节学习工作。
首先,先提供给大家一个api官网,开发者必备手册,地址:https://golang.org/cmd/api/
当然,可能有的朋友没有VPN,连接不上官网,有一个本地查看文档的方式,如下:
也为大家推荐了技术教程:
-
$> go help doc
-
usage: go doc [-u] [-c] [package|[package.]symbol[.method]]
-
Doc prints the documentation comments associated with the item identified by its
-
arguments (a package, const, func, type, var, or method) followed by a one-line
-
summary of each of the first-level items "under" that item (package-level
-
declarations for a package, methods for a type, etc.).
-
Flags:
-
-c
-
Respect case when matching symbols.
-
-cmd
-
Treat a command (package main) like a regular package.
-
Otherwise package main's exported symbols are hidden
-
when showing the package's top-level documentation.
-
-u
-
Show documentation for unexported as well as exported
-
symbols and methods.
或者使用http,浏览器方式查看
$> godoc -http=:8080
接下来,你就可以使用 http://localhost:8080 或 http://127.0.0.1:8080 在本地使用浏览器进行浏览api文档了。
1、什么是包(package)?
我们在使用其它语言的情况,比如Java(本主是Java开发出身,0rz,以此为例),是有“包”这个概念的,其实,就可以简单的理解为是便于管理和组织所有的文件所使用的,比如java中常用的类String,它就隶属于“java.lang”包下的类。(当然,新手不理解也没有关系)。在Go当中,也是类似的概念,它将我们的go文件(文件的后缀名为“.go”)组织起来,可以方便进行归类、复用等。
你会看到这样的一些文件结构,比如encoding包,下面就有base32、base64、hex、json等等,当需要使用时,则
-
//使用“import”关键字进行导入,比如:
-
import "fmt"
在开篇《入门篇》中,所讲到的编写“hello world”使用了“fmt”,就使用这样的导入方式,当需要导入多个包时,可以使用
-
import (
-
"fmt"
-
"os"
-
)
包的命名
go语言的包的命名,遵循简洁、小写、和go文件所在目录同名的原则,这样就便于我们引用,书写以及快速定位查找。对于在企业当中开发的程序而言,我们一般采用域名作为顶级包名的方式,这样就不用担心和其他开发者包名重复的问题了,比如公司的域名是`www.bboyHan.com`,那么开发的go程序都以`bboyHan.com`作为全路径中的最顶层部分,导入开发的工具包则可以写为:
-
package main
-
import "bboyHan.com/utils"
------------------------------------------------------------
2、Main
我们知道,在java当中,有一个主程序的入口main()方法,而Go语言程序,也是类似。当把一个go文件的包名声明为main时,就等于告诉go编译程序,这是一个可执行程序,那么go编译程序就会尝试把它编译为一个二进制的可执行文件。如果没有这个函数,程序就无法执行。
-
//注意点:在go语言里,同时要满足main包和包含main()函数,才会被编译成一个可执行文件。
-
package main
-
import "fmt"
-
func main(){
-
fmt.Println("接下来,请在这里搞事情。")
-
}
那么,思考一个问题:Go编译器又是如何去寻找各个文件、包之间的依赖关系而构建程序的呢?
在上一文当中,我们提到了环境变量GOROOT和GOPATH两个概念,这是两个定义路径的环境变量,GOROOT是安装Go的路径,比如 C:\go ;GOPATH是我们自己定义的开发者个人的工作空间,比如C:\workspace\src\bbboyHan。
编译器会使用我们设置的这两个路径,再加上import导入的相对全路径来查找磁盘上的包,比如我们导入的fmt包,编译器最终找到的是 C:\go\fmt 这个位置。对于包的查找,是有优先级的,编译器会优先在GOROOT里搜索,其次是GOPATH,一旦找到,就会马上停止搜索。如果最终都没找到,就会报编译异常了。
------------------------------------------------------------
3、变量
Go中使用全新的关键字var来声明变量。var我们并不陌生,在Javascript 和C#中均有出现。不同的是Go和C#中变量属于强类型,在声明变量后就不允许改变其数据类型。记住,Go属于强数据类型
声明及初始化
-
var a int //声明一个int类型的变量
-
var b struct { //声明一个结构体
-
i string
-
}
-
var a = 1 //声明变量的同时赋值,编译器自动推导其数据类型
-
a := 1 //这种方式,含义同上,不书写类型,编译时会根据value自动推导类型进行匹配
-
var a int = 2 //声明变量的同时赋值
-
var { //批量声明变量,简洁
-
a int
-
b string
-
}
值得注意的一点,赋值时如果要确定你想要的类型,在Go中是不支持隐式转换的。如果是定义个float64类型的变量,请写为
-
//前提:需要定义一个float类型的变量时:
-
//正确写法
-
v1 := 3.0
-
//错误写法
-
v1 := 3
------------------------------------------------------------
4、常量
使用constant关键字进行定义,官方文档内容
-
const a = 2 + 3.0 // a == 5.0 (untyped floating-point constant)
-
const b = 15 / 4 // b == 3 (untyped integer constant)
-
const c = 15 / 4.0 // c == 3.75 (untyped floating-point constant)
-
const Θ float64 = 3/2 // Θ == 1.0 (type float64, 3/2 is integer division)
-
const Π float64 = 3/2. // Π == 1.5 (type float64, 3/2. is float division)
-
const d = 1 << 3.0 // d == 8 (untyped integer constant)
-
const e = 1.0 << 3 // e == 8 (untyped integer constant)
-
const f = int32(1) << 33 // illegal (constant 8589934592 overflows int32)
-
const g = float64(2) >> 1 // illegal (float64(2) is a typed floating-point constant)
-
const h = "foo" > "bar" // h == true (untyped boolean constant)
-
const j = true // j == true (untyped boolean constant)
-
const k = 'w' + 1 // k == 'x' (untyped rune constant)
-
const l = "hi" // l == "hi" (untyped string constant)
-
const m = string(k) // m == "x" (type string)
-
const Σ = 1 - 0.707i // (untyped complex constant)
-
const Δ = Σ + 2.0e-4 // (untyped complex constant)
-
const Φ = iota*1i - 1/1i // (untyped complex constant)
------------------------------------------------------------
有趣的一点,就是Go在一些情况下,会做一些调整,比如:
-
func main(){
-
a :=8
-
a =8.5 // 将编译错误:constant 8.5 truncated to integer
-
fmt.Println(a)
-
}
-
func main(){
-
a := 3
-
a = 3.0 // 编译可通过,运行无错误
-
fmt.Println(a)
-
}
也就是说,Go在不损失精度的情况下会把3.0这类浮点数视作整数3,如果类型显式指定了,在表达式当中就不会产生变化。在使用的时候会根据上下文需要的类型转化为实际类型,比如uint8(0) + 1.0就是uint8(1),但是uint8(0)+2.2就会由于2.2无法转化为uint8而报错。
当多个常量需要定义时,也可以使用简易写法:
-
//相同类型的情况:
-
const c_name1, c_name2 = value1, value2
-
//可以用作枚举
-
const (
-
Unknown = 0
-
Female = 1
-
Male = 2
-
)
-----------------------------------------------------------
5、iota
iota,特殊常量,可以认为是一个可以被编译器修改的常量。在每一个const关键字出现时,被重置为0,然后再下一个const出现之前,每出现一次iota,其所代表的数字会自动增加1。
-
const (
-
a = iota //a = 0
-
b = iota //b = 1
-
c = iota //c = 2
-
)
-
//可简写为:
-
const (
-
a = iota
-
b
-
c
-
)
-
//进阶用法:
-
const (
-
i = 1<<iota //i = 1
-
j = 3<<iota //j = 6
-
k //k = 12
-
l //l = 24
-
)
-----------------------------------------------------------
6、数组
-
var array [5]int //声明
-
array = [5]int{1,2,3,4,5} //初始化
-
array := [5]int{1,2,3,4,5} //声明并初始化
-
array := [...]int{1,2,3,4,5} //不指定长度进行声明及初始化
-
array := [5]int{1:1,3:4} //只对索引为1和3的值初始化,其余使用默认初始化值0
因为数组的创建在内存当中是一段连续的空间,所以通过索引进行直接访问,访问的效率非常高
-
func main() {
-
array := [5]int{1: 1, 3: 4}
-
for i := 0; i < 5; i++ {
-
fmt.Printf("索引:%d,值:%d\n", i, array[i])
-
}
-
}
-----------------------------------------------------------
看了上面的代码,想必会有朋友会问“fmt”还没有讲呢,下面讲解一下fmt包的相关知识
7、“fmt”
fmt包实现了格式化的I/O函数,这点类似C语言中的printf和scanf,但是更加简单,其中的格式“占位符”衍生自 C
-
//常用的格式化输出
-
fmt.Printf("start at number %v, end count %v\n",start, count)
占位符
一般占位符
符号 | 说明 |
---|---|
%v | 相应值的默认格式 |
%+v | 在打印结构体时,默认格式,会添加字段名 |
%#v | 相应值的 Go 语法表示 |
%T | 相应值的类型的 Go 语法表示 |
%% | 字面上的百分号,并非值的占位符 |
布尔占位符
符号 | 说明 |
---|---|
%t | 单词 true 或 false |
整数占位符
符号 | 说明 |
---|---|
%b | 二进制表示 |
%c | 相应 Unicode 码点所表示的字符 |
%d | 十进制表示 |
%o | 八进制表示 |
%q | 单引号围绕的字符字面值,由 Go 语法安全地转义 |
%x | 十六进制表示,字母形式为小写 a-f |
%X | 十六进制表示,字母形式为大写 A-F |
%U | Unicode 格式:U+1234,等同于 "U+%04X" |
浮点数及其复合构成占位符
符号 | 说明 |
---|---|
%b | 无小数部分的,指数为二的幂的科学计数法,与 strconv.FormatFloat 的 'b' 转换格式一致。例如 -123456p-78 |
%e | 科学计数法,例如 -1234.456e+78 |
%E | 科学计数法,例如 -1234.456E+78 |
%f | 有小数点而无指数,例如 123.456 |
%g | 根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的 0)输出 |
%G | 根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的 0)输出 |
字符串与字节切片占位符
符号 | 说明 |
---|---|
%s | 字符串或切片的无解译字节 |
%q | 双引号围绕的字符串,由 Go 语法安全地转义 |
%x | 十六进制,小写字母,每字节两个字符 |
%X | 十六进制,大写字母,每字节两个字符 |
指针
符号 | 说明 |
---|---|
%p | 十六进制表示,前缀 0x |
fmt中的方法:
-
// Print 将参数列表 a 中的各个参数转换为字符串并写入到标准输出中。
-
// 非字符串参数之间会添加空格,返回写入的字节数。
-
func Print(a ...interface{}) (n int, err error)
-
// Println 功能类似 Print,只不过最后会添加一个换行符。
-
// 所有参数之间会添加空格,返回写入的字节数。
-
func Println(a ...interface{}) (n int, err error)
-
// Printf 将参数列表 a 填写到格式字符串 format 的占位符中。
-
// 填写后的结果写入到标准输出中,返回写入的字节数。
-
func Printf(format string, a ...interface{}) (n int, err error)
-
// 功能同上面三个函数,只不过将转换结果写入到 w 中。
-
func Fprint(w io.Writer, a ...interface{}) (n int, err error)
-
func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
-
func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
-
// 功能同上面三个函数,只不过将转换结果以字符串形式返回。
-
func Sprint(a ...interface{}) string
-
func Sprintln(a ...interface{}) string
-
func Sprintf(format string, a ...interface{}) string
-
// 功能同 Sprintf,只不过结果字符串被包装成了 error 类型。
-
func Errorf(format string, a ...interface{}) error
文末彩蛋:
1.CSDN学院助学会员:仅需百元- 1300门课+600次下载特权,一次购买,全年无忧!点击查看。
2.CSDN学院知识周刊:每周更新学院优惠课程活动及精品上新内容,点击查看!
3.技术教程推荐: