02 . Go语言的变量,常量,作用域及第一个程序HelloWorld
第一个Go程序
Hello World
package main
// Go源文件以package声明开头,说明源文件所属的包
import "fmt"
// 使用import 导入依赖的包,其此为包级别的变量,常量,类型和函数的声明和赋值
func main() {
// 函数内可以定义局部的变量,常量
fmt.Println("Hello World")
}
// 运行
youmen@youmendeMacBook-Pro src % go build hello.go
youmen@youmendeMacBook-Pro src % ./hello
Hello World
youmen@youmendeMacBook-Pro src % go run hello.go
Hello World
// go build 编译自身包和依赖包
// go install 编译并安装自身包和依赖包
// go fmt 格式化输出代码
// 参数
// -I 针对包的目录搜索
// -d 打印声明信息
// -e 不限制错误打印的个数
// -f 打印栈结构
// -h 发生错误时进入恐慌(panic)状态
// -o 指定输出文件名
// -S 打印产生的汇编代码
// -V 打印编译器版本
// -u 禁止使用 unsafe 包中的代码
// -w 打印归类后的语法解析树
// -x 打印 lex tokens
youmen@youmendeMacBook-Pro day01 % go build -x hello.go
WORK=/var/folders/2k/bdg95_md7qxbnwbh1b86qcmm0000gn/T/go-build023067131
mkdir -p $WORK/b001/
cat >$WORK/b001/importcfg.link << 'EOF' # internal
packagefile command-line-arguments=/Users/youmen/Library/Caches/go-build/f9/f949be0d2820ac87750eb4d2c59a7e18e1ffab7c94db4ed324d0fa8df5d8896a-d
packagefile fmt=/usr/local/go/pkg/darwin_amd64/fmt.a
packagefile runtime=/usr/local/go/pkg/darwin_amd64/runtime.a
packagefile errors=/usr/local/go/pkg/darwin_amd64/errors.a
packagefile internal/fmtsort=/usr/local/go/pkg/darwin_amd64/internal/fmtsort.a
packagefile io=/usr/local/go/pkg/darwin_amd64/io.a
packagefile math=/usr/local/go/pkg/darwin_amd64/math.a
packagefile os=/usr/local/go/pkg/darwin_amd64/os.a
packagefile reflect=/usr/local/go/pkg/darwin_amd64/reflect.a
packagefile strconv=/usr/local/go/pkg/darwin_amd64/strconv.a
packagefile sync=/usr/local/go/pkg/darwin_amd64/sync.a
packagefile unicode/utf8=/usr/local/go/pkg/darwin_amd64/unicode/utf8.a
packagefile internal/bytealg=/usr/local/go/pkg/darwin_amd64/internal/bytealg.a
packagefile internal/cpu=/usr/local/go/pkg/darwin_amd64/internal/cpu.a
packagefile runtime/internal/atomic=/usr/local/go/pkg/darwin_amd64/runtime/internal/atomic.a
packagefile runtime/internal/math=/usr/local/go/pkg/darwin_amd64/runtime/internal/math.a
packagefile runtime/internal/sys=/usr/local/go/pkg/darwin_amd64/runtime/internal/sys.a
packagefile internal/reflectlite=/usr/local/go/pkg/darwin_amd64/internal/reflectlite.a
packagefile sort=/usr/local/go/pkg/darwin_amd64/sort.a
packagefile sync/atomic=/usr/local/go/pkg/darwin_amd64/sync/atomic.a
packagefile math/bits=/usr/local/go/pkg/darwin_amd64/math/bits.a
packagefile internal/oserror=/usr/local/go/pkg/darwin_amd64/internal/oserror.a
packagefile internal/poll=/usr/local/go/pkg/darwin_amd64/internal/poll.a
packagefile internal/syscall/execenv=/usr/local/go/pkg/darwin_amd64/internal/syscall/execenv.a
packagefile internal/syscall/unix=/usr/local/go/pkg/darwin_amd64/internal/syscall/unix.a
packagefile internal/testlog=/usr/local/go/pkg/darwin_amd64/internal/testlog.a
packagefile syscall=/usr/local/go/pkg/darwin_amd64/syscall.a
packagefile time=/usr/local/go/pkg/darwin_amd64/time.a
packagefile unicode=/usr/local/go/pkg/darwin_amd64/unicode.a
packagefile internal/race=/usr/local/go/pkg/darwin_amd64/internal/race.a
EOF
mkdir -p $WORK/b001/exe/
cd .
/usr/local/go/pkg/tool/darwin_amd64/link -o $WORK/b001/exe/a.out -importcfg $WORK/b001/importcfg.link -buildmode=exe -buildid=rVXQxABwQkdy_FI00RsL/yf_AjuJJYda-p8wMA7El/EVj7Mr4eTh1CznhPCir7/rVXQxABwQkdy_FI00RsL -extld=clang /Users/youmen/Library/Caches/go-build/f9/f949be0d2820ac87750eb4d2c59a7e18e1ffab7c94db4ed324d0fa8df5d8896a-d
/usr/local/go/pkg/tool/darwin_amd64/buildid -w $WORK/b001/exe/a.out # internal
mv $WORK/b001/exe/a.out hello
rm -r $WORK/b001/
注释
// 定义main包
package main // 定义包main
import "fmt" // 导入标准包fmt
// 程序入口,main函数
func main() {
/*
我是一个注释
这里调用fmt包下的Println的函数打印内容到控制台
*/
fmt.Println("hello world") // 打印helloworld到控制台
}
Go安装目录清单
# /bin:包含可执行文件,如:编译器,Go 工具
# /doc:包含示例程序,代码工具,本地文档等
# /lib:包含文档模版
# /misc:包含与支持 Go 编辑器有关的配置文件以及 cgo 的示例
# /os_arch:包含标准库的包的对象文件(.a)
# /src:包含源代码构建脚本和标准库的包的完整源代码(Go 是一门开源语言)
# /src/cmd:包含 Go 和 C 的编译器和命令行脚本
Go运行时(runtime)
尽管 Go 编译器产生的是本地可执行代码,这些代码仍旧运行在 Go 的 runtime(这部分的代码可以在 runtime 包中找到)当中。这个 runtime 类似 Java 和 .NET 语言所用到的虚拟机,它负责管理包括内存分配、垃圾回收、栈处理、goroutine、channel、切片(slice)、map 和反射(reflection)等等。
runtime 主要由 C 语言编写(Go 1.5 开始自举),并且是每个 Go 包的最顶级包。你可以在目录
$GOROOT/src/runtime中找到相关内容。
垃圾回收器
Go 拥有简单却高效的标记-清除回收器。它的主要思想来源于 IBM 的可复用垃圾回收器,旨在打造一个高效、低延迟的并发回收器。目前 gccgo 还没有回收器,同时适用 gc 和 gccgo 的新回收器正在研发中。使用一门具有垃圾回收功能的编程语言不代表你可以避免内存分配所带来的问题,分配和回收内容都是消耗 CPU 资源的一种行为。
Go 的可执行文件都比相对应的源代码文件要大很多,这恰恰说明了 Go 的 runtime 嵌入到了每一个可执行文件当中。当然,在部署到数量巨大的集群时,较大的文件体积也是比较头疼的问题。但总的来说,Go 的部署工作还是要比 Java 和 Python 轻松得多。因为 Go 不需要依赖任何其它文件,它只需要一个单独的静态文件,这样你也不会像使用其它语言一样在各种不同版本的依赖文件之间混淆。
Go环境变量
Go 开发环境依赖于一些操作系统环境变量,你最好在安装 Go 之前就已经设置好他们。如果你使用的是 Windows 的话,你完全不用进行手动设置,Go 将被默认安装在目录
c:/go下。这里列举几个最为重要的环境变量:
// $GOROOT 表示 Go 在你的电脑上的安装位置,它的值一般都是 $HOME/go,当然,你也可以安装在别的地方。
// $GOARCH 表示目标机器的处理器架构,它的值可以是 386、amd64 或 arm。
// $GOOS 表示目标机器的操作系统,它的值可以是 darwin、freebsd、linux 或 windows。
// $GOBIN 表示编译器和链接器的安装位置,默认是 $GOROOT/bin,如果你使用的是 Go 1.0.3 及以后的版本,
// 一般情况下你可以将它的值设置为空,Go 将会使用前面提到的默认值。
// 目标及其是指你打算运行你的Go应用程序的机器
Go 编译器支持交叉编译,也就是说你可以在一台机器上构建运行在具有不同操作系统和处理器架构上运行的应用程序,也就是说编写源代码的机器可以和目标机器有完全不同的特性(操作系统与处理器架构)。
为了区分本地机器和目标机器,你可以使用 $GOHOSTOS 和 $GOHOSTARCH 设置本地机器的操作系统名称和编译体系结构,这两个变量只有在进行交叉编译的时候才会用到,如果你不进行显示设置,他们的值会和本地机器($GOOS 和 $GOARCH)一样。
- $GOPATH 默认采用和
$GOROOT一样的值,但从 Go 1.1 版本开始,你必须修改为其它路径。它可以包含多个 Go 语言源码文件、包文件和可执行文件的路径,而这些路径下又必须分别包含三个规定的目录:src、pkg和bin,这三个目录分别用于存放源码文件、包文件和可执行文件。 - $GOARM 专门针对基于 arm 架构的处理器,它的值可以是 5 或 6,默认为 6。
- $GOMAXPROCS 用于设置应用程序可使用的处理器个数与核数,详见第 14.1.3 节。
生成代码文档
go doc工具会从 Go 程序和包文件中提取顶级声明的首行注释以及每个对象的相关注释,并生成相关文档。它也可以作为一个提供在线文档浏览的 web 服务器,http://golang.org 就是通过这种形式实现的。
一般用法
# go doc package 获取包的文档注释,例如:go doc fmt 会显示使用 godoc 生成的 fmt 包的文档注释。
# go doc package/subpackage 获取子包的文档注释,例如:go doc container/list。
# go doc package function 获取某个函数在某个包中的文档注释,例如:go doc fmt Printf 会显示有关 fmt.Printf() 的使用说明。
# 这个工具只能获取在 Go 安装目录下 ../go/src 中的注释内容。此外,它还可以作为一个本地文档浏览 web 服务器。
# 在命令行输入 godoc -http=:6060,然后使用浏览器打开 http://localhost:6060 后,
# 你就可以看到本地文档浏览服务器提供的页面。
变量
变量概念
-
变量是计算机语言中存储数据的抽象概念,变量的功能就是存储数据,变量通过变量名访问
-
变量的本质是计算机分配的一小块内存,专门用于存放指定数据,在程序中该数值可以发生改变
-
变量的存储往往具有瞬时性,或者说是临时存储,当程序运行结束,存放该数据的内存就会释放,而该变量就会消失.
-
Go语言的变量由字母,数字下划线组成,首个字符不能为数字;
-
Go语法规定,定义的局部变量若没有被调用则编译错误
声明变量
1.未初始化的标准格式
# var 变量名 变量类型
func variableZeroValue() {
var a int
var s string
fmt.Printf("%d %q\n",a,s)
}
2.未初始化的批量格式
var (
aa = 3
ss = "kkk"
)
// 不用每行都用var声明
// 未初始化变量的默认值
// 整形和浮点型变量默认值: 0
// 字符串默认值为空字符串
// 布尔型默认为false
// 函数,指针变量值为nil
3.初始化变量的标准格式
// var 变量名 类型 = 表达式
var k = "zhou"
4.初始化变量的编译器自动推断类型格式
# var 变量名 = 表达式
func var_demo1() {
a := 3+4
fmt.Println(a)
}
5.初始化变量的简短声明格式(短变量声明格式)
func varialbeShorter() {
a,b,c,s := 3,4,true,"def"
// := 能写的短一点,但是函数外不能这样定义
fmt.Println(a,b,c,s)
}
# 变量名 := 表达式
# 使用 := 赋值操作符, :=可以高效的创建一个新的变量,称之为初始化声明
# 声明语句省略了var关键字
# 变量类型将由编译器自动推断
# 这是声明变量的首选形式但是它只能被用在函数体内,而不可以用于全局变量的声明与赋值
# 该变量名必须是没有定义过的变量,若定义过,将发生编译错误
# 在多个短变量声明和赋值中,至少有一个新声明的变量出现在左侧中,
# 那么即便有其它变量名可能是重复声明的,编译器也不会报错。
变量多重赋值
多个变量同时赋值
# Go语法中,变量初始化和变量赋值是两个不同的概念。Go语言的变量赋值与其他语言一样,
# 但是Go提供了其他程序员期待已久的多重赋值功能,可以 实现变量交换。
# 多重赋值让Go语言比其他语言减少了代码量。
匿名变量
# Go语言的函数可以返回多个值,而事实上我们并不是对所有的返回值都用 得上。那么就可以使用匿名变量,用“一 ”下划线替换即可。
# 匿名变量不占用命名空间,不会分配内存。
常量
声明方式
1、相对于变量,常量是恒定不变的值,例如圆周率。
常量是一个简单值的标识符,在程序运行时,不会被修改。
2、常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符 串型。
3、常量的定义格式:
# const标识符[类型]=值
# 可以省略类型说明符[type],因为编译器可以根据变量的值来自动推断其 类型。
# 显式类型定义:const B string = "Steven"
# 隐式类型定义:const C = "Steven"
4、多个相同类型的声明可以简写为:
# const WIDTH , HEIGHT = value1, value2
5、常量定义后未被使用,不会在编译时出错。
Example
package main
import "fmt"
func consts_demo() {
const (
C5 int = iota
C6
C7
)
const (
C1 string = "qinhua"
C2 string = "beida"
)
const C3,C4 = "wuda","huake"
const NAME string = "zhou"
const AGE int = 18
fmt.Println(NAME,AGE,C1,C2,C3,C4,C5,C6,C7)
}
func main() {
consts_demo()
}
// 输出信息
// zhou 18 qinhua beida wuda huake 0 1 2
枚举(常量组)
例如以下格式
package main
import "fmt"
const(
Unknown = 0
Famale = 1
Male = 2
// 数字0,1,2分别代表未知性别,女性和男性
)
const (
// 常量组中如果不指定类型和初始值,则与上一行非空常量值相同
a = 10
b
c
)
func main() {
fmt.Println(Unknown,Famale,Male,a,b,c)
}
// 输出结果
0 1 2 10 10 10
iota
1 . iota,特殊常量值,是一个系统定义的可以被编译器修改的常量值。iota只能用 在常量赋值中。
2 . 在每一个const关键字出现时,被重置为0,然后每出现一个常量,iota所代表的数值会自动增加1, iota可以理解为常量的计数器,不论该常量的值是什么,只要有一个常量,那么iota就加1.
3 . iota可以被用作枚举值
Example1
package main
import "fmt"
const (
a = iota
b = iota
c = iota
// 第一个iota等于0,每当iota在新的一行被使用时,他的值都会自动加1
)
const (
// 我们可以简写为以下格式
d = iota
e
f
)
func main() {
fmt.Println(a, b, c)
fmt.Println(d,e,f)
}
Example2
package main
import "fmt"
const (
i = 1<<iota
j = 3<<iota
k
l
)
const (
ai ='—'
bi
ci = iota
di
)
func main() {
fmt.Println("i=",i)
fmt.Println("j=",j)
fmt.Println("k=",k)
fmt.Println("l=",l)
fmt.Println(ai,bi,ci,di)
}
作用域
作用域
作用域是指变量可以使用范围,Go语言使用大括号显示的标识作用域范围,大括号内包含一连串的语句,叫做语句块,语句块可以嵌套,语句块内定义的变量不能在语句块外使用;
package main
import "fmt"
// 作用域内定义变量只能被声明一次必须使用,否则编译错误,
// 在不同作用域可定义相同的变量,此时局部变量将覆盖全局
func main() {
// 作用域: 定义标识符可以使用的范围
// 在Go中用{}来定义作用域的范围
// 使用原则: 子语句块可以使用父语句块中的标识符,父不能用子的
outer := 1
{
innner :=2
fmt.Println(outer)
fmt.Println(innner)
outer := 21
{
inner2 :=3
fmt.Println(outer,innner,inner2)
}
}
fmt.Println("hello")
}
// 输出
// 1
// 2
// 21 2 3
// hello
打印
fmt.Print(name) // 只会打印变量不会换行
fmt.Println(name) // 打印变量加换行
fmt.Printf("%T,%T",name,name) //占位符
Go编译成不同平台二进制包
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go

浙公网安备 33010602011771号