安装包下载地址:https://golang.org/dl/,打不开可以在https://studygolang.com/dl下载。
安装集成开发环境
liteIDE下载地址:http://liteIDe.org/cn/
可以使用Go的集成开发环境liteIDE,或是IntelliJ IDea安装Go插件。
插件安装路径:file->Settings
每个go文件的第一行声明该文件属于哪个包,package 包名 定义该文件的包名,main包表示独立可运行的go程序,每个go应用程序都包含一个叫main的包。
package main
包的导入使用import关键字 + 包名导入依赖的包,包名使用双引号。
import "fmt"import "math"
也可以使用圆括号分组形式导入包
import ( "fmt" "math")
导出名在go中,只能使用模块中已导出的函数,已导出的函数都以大写字母开头。小写字母开头的方法只能在包内使用。
package mainimport ("fmt" "math")func main() { fmt.Printf("%g", math.Sqrt(2))}
package mainimport ("fmt" "math")func main() { fmt.Printf("%g", math.sqrt(2))}
函数函数定义go中的函数使用func关键字定义,注意参数类型在参数名之后,格式如下
func 函数名(参数名1 参数类型, 参数名2 参数类型) 返回值 {}
package mainimport ( "fmt")func main() { fmt.Printf("3 + 5 = %d", add(3, 5))}func add(a int, b int) int { return a + b}
参数列表简化当两个或以上参数类型相同时,参数类型可只保留最后一个,如上函数add可简化为
func add(a, b int) int { return a + b}
多返回值go中的函数可返回任意数量的返回值
package mainimport ( "fmt")func main() { a, b := add(3, 5) fmt.Printf("3 + 5 = %d, 3 - 5 = %d", a, b)}func add(a, b int) (int, int) { return a + b, a - b}
返回值的命名可以直接命名返回值,没有参数的return语句返回已命名的返回值
func add(a, b int) (sum, difference int) { sum = a + b difference = a - b return}
变量变量使用var关键字定义,作用域可以是包或函数。
var flag boolfunc main() { var i int flag = true i = 5 fmt.Println(i, flag)}
变量的初始化变量可以在声明时初始化,如果变量在声明时初始化值可省略类型,变量可以从值中获取类型。
var flag = truefunc main() { var i = 5 fmt.Println(i, flag)}
短赋值语句在函数里:=可以取代类型明确的变量赋值中的var声明,但在函数外不可以使用
func main() { i := 5 fmt.Println(i, flag)}
基本数据类型go中的基本数据类型同样可分为整型、浮点型、布尔型三大类
整型整型的数据类型包含int8、int16、int32、int64、uint8、uint16、uint32、uint64,其中int开头的为有符号整型,unit开头的位无符号整型
浮点型浮点型的数据类型包含float32、float64、complex64、complex128、uint8、uint16、uint32、uint64,其中int开头的为有符号整型,unit开头的位无符号整型。
float用于表示浮点数据,complex用于表是复数类型
布尔型的值只可以是常量 true 或者 false
其他数字类型其他数字类型包括byte、rune。
byte 等同于int8,常用来处理ascii字符
rune 等同于int32,常用来处理unicode或utf-8字符
// rune is an alias for int32 and is equivalent to int32 in all ways. It is// used, by convention, to distinguish character values from integer values.//int32的别名,几乎在所有方面等同于int32//它用来区分字符值和整数值type rune = int32
零值没有赋值的变量会被设置为零值
数字型:0
布尔型:false
字符串:""
package mainimport ( "fmt")var ( flag bool MaxInt uint64 str string)func main() { fmt.Printf("Type: %T Value: %v\n", flag, flag) fmt.Printf("Type: %T Value: %v\n", MaxInt, MaxInt) fmt.Printf("Type: %T Value: %v\n", str, str)}
分支结构go语言中的循环结构只有for一种
for对比其他语言,go中的for的小括号可以省略
sum := 0 for i:= 1; i < 100; i ++ { sum += i } fmt.Printf("sum = %v", sum)
除了条件表达式外,初始化语句和后置语句是可选的
sum := 1 for sum < 10 { sum += sum } fmt.Printf("sum = %v", sum)
无限循环语句可视作没有条件表达式的for语句
for { }
ifif语句和for语句类似,小括号可以省略,大括号不行
flag := true if flag { fmt.Printf("true") } else { fmt.Printf("false") }
if 可以在条件表达式判定之前先做一些初始化的语句,该语句的作用域仅在if语句内有效
import ( "fmt" "math")func pow(x, n, lim float64) float64 { if v := math.Pow(x, n); v < lim { return v } return lim}func main() { fmt.Println( pow(3, 2, 10), pow(3, 3, 20), )}
switchgo中的switch 的 case 语句从上到下顺次执行,直到匹配成功时停止,不会发生case穿透,只会执行第一个满足条件的case而不会执行后面的case
import ( "fmt" "runtime")func main() { fmt.Print("Go runs on ") switch os := runtime.GOOS; os { case "darwin": fmt.Println("OS X.") case "linux": fmt.Println("linux.") case "windows": fmt.Println("windows") default: fmt.Printf("NulL") }}
deferdefer修饰的语句会被推到调用栈里,待外层函数返回后执行,如果有多条语句用defer修饰,遵循后进先出的顺序
fmt.Println("counting") for i := 0; i < 10; i++ { defer fmt.Println(i) } fmt.Println("done")
指针go中有指针,但不允许进行指针计算,* 类型声明这种类型的指针,零值为<nil>。
使用& *** 作符生成指向指定 *** 作数的指针。
func main() { i := 1 var p *int fmt.Println(p) p = &i//定义指向变量i的指针p fmt.Println(p)//变量i在内存中的存放地址 fmt.Println(*p) *p = *p + 1 fmt.Println(*p)}
结构体结构体(struct)就是一组字段,使用.号访问结构体中的字段
type Coordinate struct { X int Y int}func main() { v := Coordinate{1, 2} fmt.Println(v.X)}
可使用结构体指针访问数据,也可以隐式间接引用
type Coordinate struct { X int Y int}func main() { var p *Coordinate p = &Coordinate{1, 2} fmt.Println((*p).X)//通过结构体指针访问 fmt.Println(p.X)//隐式间接访问}
可使用列出字段值的方法来分配结构体,未被分配值的字段为该类型的零值
type Coordinate struct { X int Y int}func main() { var p *Coordinate p = &Coordinate{X:1} fmt.Println((*p).X) fmt.Println(p.Y)}
数组go中使用 []类型 来声明数组
func main() { a := [5]int{1,2,3,4,5} fmt.Println(a)}
切片数组的大小都是固定的。而切片则为数组元素提供动态大小的、灵活的视角。
切片通过两个下标来界定,即一个上界和一个下界,二者以冒号分隔:
包含下界不包含上界
func main() { a := [5]int{1,2,3,4,5} var p = a[0:4] fmt.Println(p)}
a[0:4]表示a数组中下标0到3的元素,切片并没有真正意义上存储数据,而只是描述数组中的一段数据,修改切片会修改数组中的对应元素。
func main() { a := [5]int{1,2,3,4,5} var p = a[0:3] var q = a[1:4] fmt.Println(p) fmt.Println(q) p[2] = 9 fmt.Println(p) fmt.Println(q)}
切片可以省略上下界,下界的默认值的0,上界的默认值为数组的长度
对于数组a [10]int,下面的切片是等价的
a[0:10]a[:10]a[0:]a[:]
切片的长度指存放的元素个数,容量指从切片第一个元素开始到底层数组最后一个元素的个数。
func main() { s := []int{1, 3, 5, 7, 9, 11} printSlice(s) // 截取切片使其长度为 0 s = s[:0] printSlice(s) // 拓展长度 s = s[:4] printSlice(s) // 舍弃前两个值 s = s[2:] printSlice(s) // 拓展长度 s = s[:4] printSlice(s)}func printSlice(s []int) { fmt.Printf("len=%d cap=%d %v\n", len(s), cap(s), s)}
切片的零值为nil且没有底层数组
func main() { var s []int fmt.Println(s, len(s), cap(s)) if s == nil { fmt.Println("nil!") }}
切片可以用内建函数make创建,双参数时第二个参数是长度和容量,三参数时第二个是长度,第三个是容量
func main() { a := make([]int, 5) fmt.Println(len(a), cap(a)) s := make([]int, 0, 5) fmt.Println(len(s), cap(s))}
可以通过append向切片追加元素,如果底层数组的容量不够,将创建新的数组,将切片指向新的数组。
func main() { var language = []string{"Java", "C", "Python"} fmt.Printf("first element address:%v, len:%d, cap:%d, %v\n", &language[0], len(language), cap(language), language) language = append(language, "Golang", "Scala", "Lua") fmt.Printf("first element address:%v, len:%d, cap:%d, %v\n", &language[0], len(language), cap(language), language)}
for 循环的 range 形式可遍历切片或映射。当使用 for 循环遍历切片时,每次迭代都会返回两个值。第一个值为当前元素的下标,第二个值为该下标所对应元素的一份副本。
var pow = []int{1, 2, 4, 8, 16, 32, 64, 128}func main() { for i, v := range pow { fmt.Printf("2**%d = %d\n", i, v) }}
range也可以将下标或值赋予 _ 来忽略它,当只需要索引时可忽略第二个变量
func main() { pow := make([]int, 10) for i := range pow { pow[i] = 1 << uint(i) // == 2**i } for _, value := range pow { fmt.Printf("%d\n", value) }}
映射map 映射将键映射到值。映射的零值为 nil 。nil 映射既没有键,也不能添加键。
make 函数会返回给定类型的映射,并将其初始化备用。
type Person struct { Weight, Height float64}var m map[string]Personfunc main() { m = make(map[string]Person) m["Bill"] = Person{ 70, 180, } fmt.Println(m["Bill"])}
如果映射的元素类型相同,可以只在外层声明类型
type Person struct { Weight, Height float64}var m map[string]Personfunc main() { m = map[string]Person{ "Bill":{70, 180}, "John":{85, 195}, } fmt.Println(m)}
可以获取修改删除映射元素,也可以使用双赋值检测某个key是否存在
type Person struct { Weight, Height float64}var m map[string]Personfunc main() { m = map[string]Person{ "Bill":{70, 180}, "John":{85, 195}, "Mary":{55, 168}, } fmt.Println(m) fmt.Println(m["John"]) m["Bill"] = Person{75, 180} fmt.Println(m) delete(m, "John") fmt.Println(m) param1, ok := m["Jack"] fmt.Println(param1, ok) param2, ok := m["Bill"] fmt.Println(param2, ok)}
go 程go中提供了轻量级的线程goroutine去执行函数,使用go 函数名执行。
import ( "fmt" "time")func say(s string) { for i := 0; i < 5; i++ { time.Sleep(100 * time.Millisecond) fmt.Println(s) }}func main() { go say("world") say("hello")}
信道信道是带有类型的管道,通过make和chan关键字创建信道,通过信道 *** 作符 <- 来发送或者接收值。
信道可以是 带缓冲的。将缓冲长度作为第二个参数提供给 make 来初始化一个带缓冲的信道,
仅当信道的缓冲区填满后,向其发送数据时才会阻塞。当缓冲区为空时,接受方会阻塞。
import "fmt"func sum(s []int, c chan int) { sum := 0 for _, v := range s { sum += v } c <- sum }func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int) go sum(s[:len(s)/2], c) go sum(s[len(s)/2:], c) x, y := <-c, <-c fmt.Println(x, y, x+y)}
如果将上述代码改成
func main() { s := []int{7, 2, 8, -9, 4, 0} c := make(chan int, 1) sum(s[:len(s)/2], c) sum(s[len(s)/2:], c) x, y := <-c, <-c fmt.Println(x, y, x+y)}
增加缓冲区同时去掉go程,则发生了锁冲突
select 语句使一个 Go 程可以等待多个通信 *** 作。select 会阻塞到某个分支可以继续执行为止,这时就会执行该分支。当多个分支都准备好时会随机选择一个执行。
当 select 中的其它分支都没有准备好时,default 分支就会执行。为了在尝试发送或者接收时不发生阻塞,可使用 default 分支:
import ( "fmt" "time")func main() { tick := time.Tick(100 * time.Millisecond) boom := time.After(500 * time.Millisecond) for { select { case <-tick: fmt.Println("tick.") case <-boom: fmt.Println("BOOM!") return default: fmt.Println(" .") time.Sleep(50 * time.Millisecond) } }}
MutexGo 标准库中提供了 sync.Mutex 互斥锁类型及其两个方法:Lock Unlock
可以通过在代码前调用 Lock 方法,在代码后调用 Unlock 方法来保证一段代码的互斥执行。
type SafeCounter struct { v map[string]int mux sync.Mutex}// Inc 增加给定 key 的计数器的值。func (c *SafeCounter) Inc(key string) { c.mux.Lock() c.v[key]++ c.mux.Unlock()}// Value 返回给定 key 的计数器的当前值。func (c *SafeCounter) Value(key string) int { c.mux.Lock() defer c.mux.Unlock() return c.v[key]}func main() { c := SafeCounter{v: make(map[string]int)} for i := 0; i < 100; i++ { go c.Inc("key") } fmt.Println(c.Value("key"))}
总结 以上是内存溢出为你收集整理的Go语言入门全部内容,希望文章能够帮你解决Go语言入门所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)