赞
踩
GOPATH可以是多个目录路径,每个目录都代表着Go语言的一个工作区。用来存放Go的源码。
源码文件通常会被放在某个工作区的 src 子目录下。那么在安装后如果产生了归档文件(以“.a”为扩展名的文件),就会放进该工作区的 pkg 子目录;如果产生了可执行文件,就可能会放进该工作区的 bin 子目录。
某个工作区的 src 子目录下的源码文件在安装后一般会被放置到当前工作区的 pkg 子目录下对应的目录中,或者被直接放置到该工作区的 bin 子目录中
go语言的主要声明有四种。变量(var)常量(const)类型(type)函数(func)。
通用形式:
var name type = expression
类型和表达式部分可以省略一个。不可以全部省略。类型省略,就由表达式决定其类型。如果表达式省略,其初始值为此类型的0值。字符串为" "。对于接口和引用类型(slice、指针、map、通道、函数)是nil。对于数组或结构体这样的复合类型,其所有元素为零值。
m := 123
主要使用在局部变量的声明和初始化中主要使用短声明。
支持多变量声明。
变量是存储值的地方。指针的值是一个变量的地址。一个指针指示值所保存的位置。不是所有值都有地址,但是所有变量都有。
var x int
,表达式&x
获取一个指向整型变量的指针,它的类型是整形指针(*int
)
取地址操作符&
。
取值操作符 *
。
x := 1
p := &x
fmt.Println(*p)
*p = 2
fmt.Println(x)
打印结果都是2。
另外一种创建变量的方式。new(T)创建一个未命名的T类型变量。初始化为零值。并返回其地址。
p := new(int)
fmt.Println(*p) // 0
*p = 2
fmt.Println(*p) // 2
下面两个函数做的是一样的事情,都是返回变量的地址。
func newInt() *int{
return new(int)
}
func newInt() *int{
var dummy int
return &dummy
}
这里有个特例:两个变量的类型不携带任何信息且是零值,例如struct{}或[0] int,当前的实现里面,它们有相同的地址。
包级别变量的生命周期是整个程序的执行时间。相反,局部变量有一个动态的生命周期:每次执行声明语句时创建一个新的实体,变量一直生存到它变得不可访问,这时它占用的存储空间被回收。函数的参数和返回值也是局部变量,它们在其闭包函数被调用的时候被创建。
垃圾回收器如何知道何时回收变量?基本思路是每一个包级别的变量,以及每一个当前执行函数的局部变量,以及每一个当前执行函数的局部变量,可以作为追溯该变量的路径源头,**通过指针和其他方式的引用可以找到变量。**如果路径不存在就代表变量不可访问。
编译器可以选择使用堆或栈上的空间来分配,这个选择并不基于new或var关键字来声明变量。
var global *int
func f() {
var x int
x = 1
global = &x
}
func g() {
y := new(int) //new传给y内存地址 初始化为0值
*y = 1
}
这里的x,一定使用的是堆空间,因为它在f函数返回以后还可以从global变量访问,尽管它是局部变量。这种情况叫x从函数f逃逸。而第二个例子变量*y变得不可访问,可回收。
每一次变量的逃逸都要额外分配内存。
多重赋值:x,y=y,x
type name underlying-type
type声明定义一个新的命名类型,它和某个已有类型使用同样的底层类型。通常为包级别
如果两个 type 都是 named type ,彼此之间不能相互赋值
type NewString string
var my string ="a"
var you NewString = my //cannot use my (type string) as type NewString in assignment
GO中包的作用是模块化、封装、编译隔离和复用。每一个包里给它声明提供独立的命名空间
包的初始化从初始化包级别的变量开始。对于包级别的每一个变量,生命周期从其值被初始化开始,对于其他一些变量,比如数据表,初始化表达式不是简单地设置它的初始值。init函数的机制会比较简单。
func init(){/*...*/}
这个函数不能被调用或引用,且它是个普通的函数。在每一个文件里,当程序启动的时候,init函数按照它们的声明顺序自动执行。
当你在import一个包的时候要确保此包已被初始化。初始化的过程都是自上而下的,main包最后初始化。main函数执行的时候其实已经所有已经初始化完毕了。
不要将作用域和生命周期混为一谈。声明语句的作用域对应的是一个源代码的文本区域;它是一个编译时的属性。一个变量的生命周期是指程序运行时变量存在的有效时间段,在此时间区域内它可以被程序的其他部分引用;是一个运行时的概念。
句法块内部声明的名字是无法被外部块访问的。这个块决定了内部声明的名字的作用域范围。
不是显示地包含在大括号中的代码声明统称词法块。包、文件、for等等都在词法块当中。当然显示的大括号代码块也算一个词法块。
一个声明的词法块决定声明的作用域大小。像int、len这种内置类型、函数或是常量在全局块中声明并且对整个程序可见。在包级别(就是任何函数外)的声明,可以被同一包里的任何文件引用,但是不能在没有另一个import语句的前提下被同一个包中其他文件中的东西引用。
一个程序可以包含多个同名的声明,但是不能在一个词法块中。
当编译器遇到一个名字的引用,寻找是从内向外的。如果内外兼有同名声明,内部词法块的声明会覆盖外部。使外部声明变得不可访问
go中不允许局部变量声明后不使用的情况,会编译报错。
var cwd string
func init(){
cwd,err := os.Getwd() // 编译错误:未使用cwd 局部变量声明
if err != nil{
log.Fatalf("os.Getwd filed:%v,", err)
}
}
为了避免这种问题最直接的解决方式,避免使用 :=
。
var cwd string
func init(){
var err error
cwd,err = os.Getwd()
if err != nil{
log.Fatalf("os.Getwd filed:%v,", err)
}
}
能跑的例子
package main var cwd int func twovaule(x int, y int) (int, int) { a, b := x, y return a, b } func main() { var err int cwd, err = twovaule(1, 2) print(err) }
Go的数据类型分四大类:基础类型 (数字 字符串 布尔值)聚合类型(数组 结构体) 引用类型(指针 函数 map slice channel) 接口类型。
整数、浮点数、复数。
字符串是不可变的字节序列,可以包含任何数据。
子串生成操作s[i:j]产生一个新字符串,内容取自原字符串字节,左闭右开区间。
字符串和子串内存分部,它们共用底层字节。
四个标准包对字符串操作特别重要:bytes、strings、strconv、Unicode。
字符串可以和字节slice相互转换:
s := "abc"
b := []byte(s)
s2 := string(b)
[]byte会分配新的字节数组。拷贝s所有字节填入,并生成一个slice引用,指向整个数组。
常量是一种表达式,其可以保证在编译阶段就计算出表达式的值。常量的值恒定。
从0取值,逐项加1.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。