基础实例
package main
import "fmt'
func main(){
fmt.Println("Hellow,world!");
}
一个go程序有且只有一个main包和main函数
fmt包为格式化输入输出包
{必须与函数名称在同一行,否则会报错
Println 表示打印换行
go语言可以用“+”连接2个字符串
变量
标准声明
var var_name var_type //先声明变量名称,再声明变量类型,和常规语言反着干
批量声明
var {
age int
name string
balance float32
}
简短声明
名字 := 表达式
只能用来定义局部变量,不能用于定义全局变量
不能提供数据类型
只能用在函数内部
变量赋值
var {
age int = 38
name string = "whoami"
balance float32 = 999.99
}
var age,name,balance = 38,"whoami",999.999
age,name,balance := 38,"whoami",999.999
变量的作用域
package main
import "fmt"
func main(){
//声明局部变量
var local1,local2,local3 int
//初始化参数
local1 = 8
local2 = 9
local3 = local1 + local2
fmt.Printf("lcoal1 = %d,local2 = %d, local3 = %d\n",local1,local2,local3)
}
全局变量
package main
import "fmt"
var global int
func main(){
//声明局部变量
var local1,local2 int
//初始化参数
local1 = 8
local2 = 9
global = local1 + local2
fmt.Printf("lcoal1 = %d,local2 = %d, global = %d\n",local1,local2,global)
}
全局变量与局部变量同名处理,在函数中局部变量会被优先考虑
package main
import "fmt"
var global int = 8
func main(){
var global int = 999
fmt.Printf("global = %d\n",global)
}
常量
//常量的值必须在编辑期间确定,否则就会报错
const e float32 = 3.1415926 //显式声明
const e = 3.1415926 //隐式声明
//const ulr = os.GetEnv("url")
常量生成器itoa
package main
import "fmt"
func main(){
type Direction int
const (
North = 10
East = iota
South
West
)
fmt.Println(' ') //很有意思,不打印空格,打印ascii对应的十进制数值32
fmt.Println(North,East,South,West) //不用自作多情加空格,go自动帮我们完成了
}
运算符
运算符优先级和数学一致
流程控制语句
ifelse语句
package main
import "fmt"
func main(){
b := 9
if b > 10 {
fmt.Println("Success!")
}else if b > 9{
fmt.Println("No!")
}else{
fmt.Println("Yes!")
}
}
for循环
go中没有while和dowhile语句
package main
import "fmt"
func main(){
product := 1
for i :=1; i < 5;i++{
product *= i
fmt.Println(product)
}
}
package main
import "fmt"
func main(){
var i int
for i <=10{
fmt.Println(i)
i++
}
}
package main
import "fmt"
func main(){
JumpLoop:
for j:=0; j<5; j++{
for i:=0; i<5; i++{
if i>3{
break JumpLoop
}
fmt.Println(i)
}
}
}
for-range语句
遍历数组、切片
package main
import "fmt"
func main(){
for key,value := range []int{0,1,-1,-2} {
fmt.Printf("key:%d value: %d\n",key,value)
}
}
遍历字符串
package main
import "fmt"
func main(){
var str = "hi 加油!"
for key,value := range str{
fmt.Printf("key:%d,value:%d\n",key,value)
}
}
遍历map
package main
import "fmt"
func main(){
m := map[string]int{
"go": 100,
"web": 99,
}
for key,value := range m{
fmt.Println(key,value)
}
}
遍历通道 channel
package main
import "fmt"
func main(){
c := make(chan int)
go func(){
c <- 7
c <- 8
c <- 9
close(c)
}()
for v := range c{
fmt.Println(v)
}
}
switch case语句
package main
import "fmt"
func main(){
var a = "3333"
switch a{
case "love","3333":
fmt.Println("love or 3333")
case "programming":
fmt.Println("programming")
default:
fmt.Println("none")
}
}
内置基础类型
boolean
func test(){
var a bool //一般声明
valid := false //简短声明
ava = true //赋值操作
}
数值类型
整数
整数类型分为无符号和带符号两种
rune int8 int16 int32 int64
byte uint8 uint16 uint32 uint64
//rune是int8别称,byte是uint8的别称
//这些类型的变量之间不允许互相赋值或操作,否则编译时引起编译器报错
浮点数
浮点数类型分为float32和float64,无float类型
复数类型,默认为complex128(64位实数+64位虚数)
package main
import "fmt"
func main(){
var c complex 64 = 5+5i
fmt.Printf("Value is %v",c)
}
字符串
go的字符串都是采用utf-8编码。字符串是用一对双引号或反引号括起来定义,类型是string, Go中字符串是不变的
package main
import "fmt"
func main(){
s := "hello"
c := []byte(s)
c[0] = 'c'
s2 := string(c)
fmt.Printf("%s\n",s2)
s1 := "Hello"
s3 := " world"
fmt.Printf("%s\n",s1+s3)
m := `hello
world`
fmt.Printf("%s\n",m)
}
技巧
分组声明
import "fmt"
import "os"
const i = 100
const pi = 3.1415
const prefix = "os_"
var i int
var pi float32
var prefix string
import (
"fmt"
"os"
)
const(
i = 100
pi = 3.1415
prefix = "GO_"
)
var(
i int
pi float32
prefix string
)
iota枚举
package main
import "fmt"
const (
x = iota
y = "10"
a,b,c = iota,iota,iota
w = iota
z
)
func main(){
fmt.Println(x,y,a,b,c,w,z)
}
Go 程序设计规则
1. 大写字母开头的变量是可导出的,其他包可以读取,属于公有变量
2. 小写字母开头的变量不可导出,属于私有变量
函数也是相同的规则
array
数组
package main
import "fmt"
func main(){
var arr [10]int //声明一个int类型的数组
arr[0] = 42 //数组下标从0开始
arr[1] = 13
fmt.Println("The first element is %d\n",arr[0])
fmt.Println("The last element is %d\n",arr[9]) //返回未赋值的最后一个元素,默认返回0
}
a := [10]int{1,2,3,4,5,6} //声明一个长度为10的数组,6以后都为0
c := [...]int{1,2,3} //自动声明一个长度为3的数组
doublearray := [2][4]int{[4]int{1,2,3,4},[4]int{6,7,8,9}}
doublearr := [2][4]int{{1,2,3,4},{5,6,7,8}} //简短声明
slice
var a,b []byte //声明动态数组
var array = [10]byte{'a','b','c','d','e','f','g','h','i','j'}
var aSlice,bSlice []byte
aSlice = array[:3] //等价于aSlice = array[0:3],包含a,b,c
aSlice = array[5:] //等价于aSlice = array[5:10],包含f,g,h,i,j
aSlice = array[:] //等价于aSlice = array[0:10],包含全部元素
slice对应数组的信息
len获取slice的长度
cap获取slice的最大容量
append想slice
slice并不是真正意义上的动态数组,而是一个引用类型,slice总是指向一个底层array,slice的声明可以像array一样,不需要长度
map
package main
import "fmt"
func main(){
rating := map[string]float32{"c":5,"Go":4.5,"python":4.5,"C++":2}
//map有两个返回值,第二个返回值,如果不存在key,那么OK为false,如果存在ok为true
csharpRating,ok := rating["c#"]
if ok{
fmt.Println("C# is in the map and its rating is ",csharpRating)
}else{
fmt.Println("We have no rating associated with c# in the map")
}
delete(rating,"c") //删除key为c的元素
}
make,new操作
make用于内建类型(map、slice和channel)的内存分配,new用于各种类型的内存分配
new返回的是指针
流程和函数
for
for k,v := range map{
fmt.Println("Map's key: ",k)
fmt.Println("Map's value: ",v)
}
//go支持多值返回
//由于 Go 支持 “多值返回”, 而对于 “声明而未被调用” 的变量,编译器会报错,在这种情况下,可以使用 _ 来丢弃不需要的返回值
for _,v := range map{
fmt.Println("Map's value is: ",v)
}
函数
fun funcName(intput type1,intput2 type2)(output type1 ,output type2){
///....
return value1,value2
}
package main
import "fmt"
func max(a,b int)(int) {
if a > b{
return a
}
return b
}
func SumAndProduct(a,b int)(int, int){
return a+b,a*b
}
/**这样可读行很好
* func SumAndProduct(A,B int)(add int, Multiplied int){
*
* add = A+B
* Multiplied = A*B
* return
*
* }
*
*
*
**/
func main(){
x := 3
y := 4
z := 5
max_xy := max(x,y)
max_xz := max(x,z)
fmt.Printf("Max(%d,%d) = %d\n",x,y,max_xy)
fmt.Printf("Max(%d,%d) = %d\n",x,z,max_xz)
fmt.Printf("Max(%d,%d) = %d\n",y,z,max(y,z))
m,b := SumAndProduct(x,y)
fmt.Printf("%d %d\n",m,b)
}
变参
func myfunc(arg ...int){}
//arg ...int告诉这个函数接受不定数量的参数,这些参数全部是int
传值和传指针
传值
package main
import "fmt"
func add(a int) int{
a = a+1
return a
}
func main(){
b := 10
c := add(b)
fmt.Println(b)
fmt.Println(c)
}
传指针
package main
import "fmt"
func add(a *int) int{
*a = *a+1
return *a
}
func main(){
b := 10
c := add(&b)
fmt.Println(b)
fmt.Println(c)
}
defer延迟语句
当函数执行到最后时,会去执行defer语句,然后返回函数
多个defer遵循后进先出的原则
package main
import "fmt"
func main(){
for i := 0;i<5;i++{
defer fmt.Println(i)
}
}
函数传参
package main
import "fmt"
type testInt func(int) bool
func isOdd(integer int)bool{
if integer %2 == 0{
return false
}
return true
}
func isEven(integer int)bool{
if integer %2 == 0{
return true
}
return false
}
func filter(slice []int,f testInt)[]int{
var result []int
for _,value := range slice{
if f(value){
result = append(result,value)
}
}
return result
}
func main(){
slice := []int{1,2,3,4,5,6}
odd := filter(slice,isOdd)
even := filter(slice,isEven)
fmt.Println("Odd is ",odd)
fmt.Println("Even is ",even)
}
main函数和init函数
GO里面有2个保留的函数:init函数(所有package)和main函数(只用于package main)
虽然一个package里面可以写任意多个init函数,但强烈建议用户在一个package中每个文件只写一个init函数
GO会自动调用main和init函数,如果有多个包,调用方式如下:
import
点操作
import (
. "fmt"
)
Println("hello,world") //.的好处是不再使用fmt
别名操作
import (
f "fmt"
)
f.Println("hello,world") //直接使用f
import (
"database/sql"
_ "github.com/ziutek/mymysql/godrv"
)
_操作其实是引入该包,而不直接使用包里面的函数,而是调用了该包里面的 init 函数。