0.项目的组织结构:
GOPATH路径下是src文件夹---->src文件夹下是项目名称---->项目名称下是该项目的各个包名---->各包名下是.go文件(一个包下,无论有多少个.go文件,同一个包下的.go文件中的方法名不得重复)
1.基础相关
package main import "fmt" // 入口函数 func main() { fmt.Println("hello world") fmt.Println("good morning") hello() s, minus := sum(2, 3) fmt.Println(minus) fmt.Println(s) var name = "tom" fmt.Println(name) convertCharacter() } // Go官方推荐用单行注释来注释代码 func hello() { fmt.Println("ddd") } // 求和,求差与多个返回值 func sum(i int, j int) (sum int, minus int) { sum = i + j minus = j - i return sum,minus } // 转义 func convertCharacter() { // 制表符 fmt.Println("a\tb\tc") // 换行符 fmt.Println("a\nb") // 一个\ fmt.Println("\\hh") // 一个" fmt.Println("\"") // 一个回车 fmt.Println("a\rb") // demo fmt.Println("姓名\t\t年龄\t\t籍贯\t\t性别\n张三\t\t23\t\t上海\t\t女") }
2.变量相关
package main import ( // 若没有用到某个包,又不删除,则在其前部加上下划线即可 "fmt" "unsafe" "strconv" ) func main() { fmt.Println(g1, g2, g3, g4) fn01() fn02() fn03() fn04() fn05() fn06() fn07() fn08() fn09() fn10() fn11() defaultFun() fn12() fn13() fn14() fn15() } //定义全局变量/// // 函数之外的变量是全局变量,一个文件中只能出现一个,不得重复定义 var g1 = 99 var g2 = "i love golang" var ( g3 = "tim" g4 = false ) //单变量声明/ func fn01() { // 第一种声明变量方式:变量=var + 变量名 + 变量类型 + 值 var i int = 8 fmt.Print(i, ",") // 该区域的数值可以在一定范围内不断变化 i = 10 fmt.Print(i, ",") i = 90 fmt.Println(i) // 不能令i = 'tim'或者i =false } func fn02() { // 第二种声明变量方式,若未赋值,则使用默认值 // int 默认值是0, string默认值是空串,小数默认是0 var i int fmt.Println(i) } func fn03() { // 第三种声明变量方式:若未定义类型,则自动类型推导 var num = 1.034 fmt.Println(num) } func fn04() { // 第四种声明变量方式:// 第二种声明变量方式:若未定义类型,则自动类型推导 name := "jerry" fmt.Println(name) } 多变量声明// func fn05() { // 第一种声明变量方式 var n1, n2, n3, n4 int fmt.Println(n1, n2, n3, n4) } func fn06() { // 第二种声明变量方式 var n1, n2, n3 = 1, "tom", 100.99 fmt.Println(n1, n2, n3) } func fn07() { // 第三种声明变量方式 n1, n2, n3 := "jerry", 3, true fmt.Println(n1, n2, n3) } func fn08() { // 程序中+号的使用 // 当都是数值型:int型,float32, float64型时,做加法运算 var ( j float64 = 1.5 k = 1.5 ) fmt.Println(k + j) // 当都是字符串时,做拼接 fmt.Println("i am " + "tom") } golang中的基本数据类型/ // 基本数据类型,也称值类型,变量存的就是值 // 整型(默认是0),浮点型(默认是0),布尔型(默认false),字符串型(默认"") func defaultFun() { var a int var b float32 var c float64 var d bool var e string fmt.Printf("基本数据类型默认值: a=%d,b=%f,c=%f,d=%v,e=%v\n",a,b,c,d,e) } /* 整型 有符号(正负号) int8(-2的7次方----2的7次方减1) int16(-2的15次方----2的15次方减1) int32(-2的31次方----2的31次方减1) int64(-2的63次方----2的63次方减1) 无符号(没有正负号 unit8(0----2的8次方) unit16(0----2的16次方) unit32(0----2的32次方) unit64(0----2的64次方) 其他类型 int 与操作系统相关,若是64位,则等价于int64;若是32位,则等价于int32 rune 等价于int32,但表示的是unicode码 byte 等价于unit8,当要存储字符时,选用byte unit 与操作系统相关,若是64位,则等价于int64;若是32位,则等价于int32 注意事项: 1.若未声明,则默认使用int型,如: var i = 10,则i为int型 2.查看变量类型及字节大小:切记是Printf fmt.Printf("i的变量类型是%T,占用的字节数是%d", i, unsafe.Sizeof(i)) 3.在保证功能的基础上,尽量选择占用内存较少的类型,如年龄尽量选取byte型 */ func fn09() { var f09 = 10 fmt.Printf("f09的变量类型是%T,占用的字节数是%d\n", f09, unsafe.Sizeof(f09)) 字符常量用单引号包裹 // golang中没有字符类型,用byte表示 var n1 byte = 'a' // 输出ascii值 fmt.Println("n1=",n1) // 输出原值 fmt.Printf("n1=%c \n",n1) // 若是超过了byte范围,则用int型 var n2 = '王' fmt.Printf("n2=%c n2的ASCII值是%d\n",n2,n2) // 给出一个数值,可以找出其对应的ASCII字符 var n3 = 29579 fmt.Printf("n3=%c\n",n3) // ASCII可以进行运算 var n4 = 10 + 'm' fmt.Println("n4=",n4) // 字符在计算机的存取过程 // 存储: 字符-->对应码值-->二进制-->存储 // 读取: 二进制-->码值-->字符-->读取 // 字符和码值的对应关系是通过字符编码表实现的,UTF-8较为常用,go语言中编码统一设置成了utf-8 // UTF-8中,一个字母占1个字节,一个汉字占3个字节 } /* 浮点型 float32:单精度,4个字节,(-2的31次方----2的31次方减1) float64:双精度,8个字节,(-2的63次方----2的63次方减1) 注意事项: 1.浮点型的存储分为三部分,符号位+指数位+尾数位,存储时,精度会有丢失 2.若未声明,默认使用float64型,如: var k = 9.99,则k为float64型 3.当对精度要求高时,尽量选取float64位 4.常量表示: n1 := 5.12e3 n2 := 4e-1 */ func fn10() { n1 := 5.12e3 n2 := 4e-1 fmt.Println(n1, n2) } /* 布尔类型(bool类型,占1个字节,主要用于逻辑运算,流程控制中会用到) true false 注意事项: 默认值是false */ func fn11() { var b = true fmt.Printf("b=%c b占用空间是%d\n",b,unsafe.Sizeof(b)) } /* string型 字符串是由一串固定长度的字符连接起来的字符序列,go中的字符串是由单个字节连接起来的 注意事项; 1.统一使用UTF-8编码 2.字符串是不可变的,一旦赋值,无法改变 3.字符串的2种表示方式: 双引号包裹: 可以识别转义字符 反引号包裹: 以字符串原生的形式输出,包括换行和转义字符,可防止攻击,输出源代码等 4.字符串拼接: var k = "aaa" + "bbb" k += "ccc" */ //golang中基本数据类型的转换/// // 数值型之间的转换 // 与Java不同,golang中无论高转低还是低转高,都需要强转 // 被转换的数据,在转换后,其数据类型与转换前保持一致 func fn12() { var n1 = 10 var n2 = int32(n1) i := n2 + 33 fmt.Println(n1, n2, i) } //基本数据类型转为string类型/// func fn13() { var n1 = 10 // int var n2 = true //bool var n3 = 3.45 // float64 var n4 byte = 35 // byte var str string // string str = fmt.Sprintf("%d",n1) // int转为string fmt.Println(str) str = fmt.Sprintf("%t", n2) // int转为bool fmt.Println(str) str = fmt.Sprintf("%f", n3) // int转为float64 fmt.Println(str) str = fmt.Sprintf("%d", n4) // int转为bool fmt.Println(str) } func fn14() { var n1 = 2 var n2 = false var n3 = 4.5 var str string str = strconv.FormatInt(int64(n1) ,10) fmt.Println(str) hhh := strconv.Itoa(n1) fmt.Println(hhh) str = strconv.FormatBool(n2) fmt.Println(str) // f:格式 3:小数点后的位数 64:表示双精度 str = strconv.FormatFloat(n3, 'f', 3, 64) fmt.Println(str) } //string类型转为基本数据类型/// func fn15() { var str1 = "true" var str2 = "123" var str3 = "12.345" // 转为bool时,会返回2个值,bool,error,可用下划线忽略error值:如果此处不是合法参数,如hello,则会直接转为false b, _ := strconv.ParseBool(str1) fmt.Println(b) // 转为int:如果此处不是合法参数,如hello,则会直接转为0 // 第二个参数是进制,第三个参数分别为0(int型),8,16,32,64 i, err := strconv.ParseInt(str2, 10, 0) fmt.Println(i, err) // 转为float:如果此处不是合法参数,如hello,则会直接转为0 f, _ := strconv.ParseFloat(str3, 64) fmt.Println(f) }
3.指针(值类型和引用类型)
package main import "fmt" func main() { pointer01() pointer02() } /* 数据类型 基本数据类型,也称值类型 值类型包括:int,float,bool,string,struct,数组 变量存的就是值 内存通常在栈中分配 引用类型包括:指针,slice切片,map,管道chan,interface 变量存储的是一个地址,这个地址对应的空间才是真正的值 内存通常在堆中分配 */ func pointer01() { var i = 1 // 这个地址和i的值在同一地方 fmt.Println("i在内存中的地址是:",&i) } 指针变量存的是一个地址,该地址指向的空间地址才是真正的值所在 /// i------------>0xc00004a080----(10)(值引用时,值和地址在同一处) /// ^ /// ^ /// ^ /// ptr---------->0xc000072020----(0xc00004a080)(指针引用时,值和地址不在一处) /// func pointer02() { var i = 1 var ptr *int = &i // 取地址 fmt.Println("ptr的值是:", &ptr) // 取值 fmt.Println("ptr的值是:", *ptr) // 通过ptr修改i的值 *ptr = 2 fmt.Println(i) }
4.标识符命名规范
因为golang中没有private,public关键字,所以以此来区分
5.运算符
5.1算术运算符
5.2关系/比较运算符
5.3逻辑运算符
5.4赋值运算符
5.5位运算符
5.6其他运算符(golang不支持三目运算符)
5.7运算符优先级
package main
import "fmt"
func main() {
fn01()
fn02()
fn03()
fn04()
fn05()
//fn06()
//fn07()
fn08()
}
// 算术运算符
func fn01() {
var i = 3
var j = 5
i2:= i + j
i3 := i - j
i4 := i * j
i5 := j / i
i6 := j % i
fmt.Println("和:",i2, ",差:", i3, ",积:", i4, ",商:", i5, ",取模:", i6)
fmt.Println((5 % 3),(5 % -3),(-5 % 3), (-5 % -3))
i ++ // 不可以 var k = i ++
fmt.Println(i)
j -- // 此外,也没有 ++j, --j这样的写法
fmt.Println(j)
}
// 关系运算符
func fn02() {
fmt.Println(2 >= 3)
fmt.Println(2 != 3)
fmt.Println(3 == 3)
fmt.Println(3 < 3)
}
// 逻辑运算符
func fn03() {
var age = 20
if age > 10 && age <= 30{
fmt.Println(true)
} else {
fmt.Println(false)
}
}
// 赋值运算符
func fn04() {
// 两个值交换:方法1:
n1 := 3
n2 := 9
t := n1
n1 = n2
n2 = t
fmt.Println(n1, n2)
// 两个值交换;方法2:
n1 = n1 + n2
n2 = n1 - n2
n1 = n1 - n2
fmt.Println(n1, n2)
}
// &(取地址) 以及 *(取指针的值) 运算符
func fn05() {
n1 := 100
fmt.Println("n1的地址是:", &n1)
ptr := &n1
fmt.Println("ptr指向的值是:", *ptr)
}
// 从控制台获取用户输入
func fn06() {
var name string
var age byte
var gender string
var sal float64
var freshMan bool
fmt.Println("请输入姓名:")
fmt.Scanln(&name)
fmt.Println("请输入年龄:")
fmt.Scanln(&age)
fmt.Println("请输入性别:")
fmt.Scanln(&gender)
fmt.Println("请输入薪水:")
fmt.Scanln(&sal)
fmt.Println("请输入是否是新人:")
fmt.Scanln(&freshMan)
fmt.Printf("姓名是%v,年龄是%v,性别是%v,薪水是%v,是否是新人%v\n",name,age,gender,sal,freshMan)
}
// 从控制台获取用户输入
func fn07() {
var name string
var age byte
var freshMan bool
fmt.Println("请输入姓名-年龄-是否是新人,中间用-连接")
fmt.Scanf("%s-%d-%t",&name,&age,&freshMan)
fmt.Printf("姓名是%v,年龄是%v,是否是新人%v\n",name,age,freshMan)
}
//进制转换///
/*
原码,反码,补码
对于有符号的而言:
二进制的最高位为符号位,0表示正数,1表示负数
正数和0的原码,反码,补码都是一样的
负数的反码=它的原码符号位不变,其他位取反(0->1,1->0)
负数的补码=它的反码+1
计算机运行的时候,都是以!!!!!!!!!!补码!!!!!!!!!!的形式进行运算的
*/
/*
其他进制转十进制:
从最低位开始,将每个位上的数提取出来,乘以2/8/16的(位数-1)次方,然后求和
二进制转十进制:
1011转为十进制: 1*2^0+1*2^1+0*2^2+1*2^3=11
八进制转十进制:
234转为十进制: 4*8^0+3*8^1+2*8^2=92
十六进制转十进制:
12转为十进制: 2*16^0+1*16^1=18
十进制转其他进制:
将该数除以2/8/16,直到商为0为止,然后将每步得到的余数倒过来,就是对应的进制
十进制转二进制: 56------->111000
十进制转8进制: 56------->70
十进制转16进制: 56------->38
二进制转为其他进制:
将二进制数从最右侧开始,每3位(8进制)或4位(16进制)一组,转为对应的进制即可
二进制转8进制: 11010101----------->11,010,101----------->0325
二进制转16进制: 11010101----------->1101,0101----------->0XD5
其他进制转为二进制:
将对应进制的每一位,转成对应的一个3位的(8进制)或者4位的(16进制)的数即可:
八进制转二进制: 023------------->010011
十六进制转二进制: 0x14----------->00010100
*/
// 位运算符
func fn08() {
var a = 1 >> 2
var b = -1 >> 2
var c = 1 << 2
var d = -1 << 2 fmt.Println(a, b, c, d) fmt.Println(2&5) fmt.Println(2|5) fmt.Println(2^5)}
6.流程控制
package main import ( "fmt" "math/rand" "time" ) func main() { //fn01() //fn02() fn03() fn04() fn05() fn06() fn07() fn08() fn09() fn10() fn11() fn12() fn13() fn14() fn15() fn16() } // 流程控制;双分支if,else func fn01() { var age int fmt.Println("请输入年龄") fmt.Scanln(&age) if age < 18 { fmt.Println("年龄不足18周岁,不得上网") }else { fmt.Println("可以上网,请继续") } } // 流程控制:多分支 if...else if...else func fn02() { var score int fmt.Println("请输入分数") fmt.Scanln(&score) if score >= 90{ fmt.Print("优秀") } else if score >= 80 { fmt.Println("良好") } else if score >= 60 { fmt.Println("及格") } else { fmt.Println("不合格") } } // switch分支,golang中不需要加break func fn03() { n1 := 7 switch n1 { case 1: fmt.Println("周一") case 2: fmt.Println("周二") case 3: fmt.Println("周三") case 4: fmt.Println("周四") case 5: fmt.Println("周五") case 6: fmt.Println("周六") case 7: fmt.Println("周日") default: fmt.Println("输入的不合法") } } // switch表达式可省略 func fn04() { n1 := 59 switch { case n1 >= 90: fmt.Println("优秀") case n1 >= 70: fmt.Println("良好") case n1 >= 60: fmt.Println("及格") default: fmt.Println("不及格,重考") } } // switch穿透:只穿透一层 func fn05() { n1 := 10 switch n1 { case 10: fmt.Println("a") fallthrough case 20: fmt.Println("b") case 30: fmt.Println("c") default: fmt.Println("d") } } // for循环 func fn06() { sum := 0 for i := 0; i <= 100; i ++{ sum += i } fmt.Println(sum) } // for循环第二种写法:sum即是增量,也是初始值 func fn07() { sum := 1 for sum < 1000 { sum += sum } fmt.Println(sum) } // for循环第三种写法:等价于for;;,是无限循环,需要结合break来使用 func fn08() { sum := 1 for{ if sum <= 10 { sum += sum } else { break } sum ++ } fmt.Println(sum) } // 遍历字符串 func fn09() { var str = "hello world" // 遍历字符串1 for i := 0; i < len(str); i ++{ //fmt.Println(str[i]) fmt.Printf("%c",str[i]) } fmt.Println() // 遍历字符串2 for index, val := range str { fmt.Printf("index=%d,val=%c\n",index,val) } fmt.Println() } // 遍历中文字符解决方案:转为切片或者采用for...range的方式,因为它是按照字符的方式遍历的 func fn10() { var str = "中国人" str2 := []rune(str) // for i := 0; i < len(str2); i ++{ fmt.Printf("%c",str2[i]) } fmt.Println() for index, val := range str{ fmt.Printf("index=%d,val=%c\n",index,val) } fmt.Println() } /golang中没有while,do...while语句 //break的使用/// // 随机生成数字,计算需要多少次,才生成80 func fn11(){ var count = 0 for{ // 返回1970.01.01至今的秒数 rand.Seed(time.Now().UnixNano()) n := rand.Intn(100) + 1 count ++ if n == 80 { break } } fmt.Println("本次随机生成80,共用了", count,"次") } // 在多层for循环中,可以给各层for循环添加label,通过break label的方式来决定终止哪一层循环 // 默认break只终止最内层循环 func fn12() { label1: for i := 0; i < 10; i ++{ for j := 0; j < i; j ++{ if j >= 3 { break label1 } fmt.Println(i + j) } } } //continue的使用 //continue只跳出本次循环,并不终止循环 func fn13() { for i:=0; i <= 4 ; i ++ { if i == 3 { continue } fmt.Println("continue:", i) } } // 在多层for循环中,可以给各层for循环添加label,通过continue label的方式来决定跳出哪一层循环 func fn14() { outer: for i:=0; i<=4 ; i ++ { for j:=0; j<=i ; j++ { if j == 3{ continue outer } fmt.Println("continue label:", i + j) } } } ///golang支持goto语句,但是不推荐使用/// func fn15() { fmt.Println("001") goto label // 将跳过002,003 fmt.Println("002") fmt.Println("003") label: fmt.Println("004") } /return表示跳出方法或函数// func fn16() { for i := 0; i <= 10 ; i ++ { fmt.Println(i) if i == 3{ return } } }
7.golang中的包
1)包的本质是创建不同的文件夹,来存放程序文件.
2)go的每一个文件都属于一个包,go是以包的形式来管理文件和项目目录结构的
3)函数名小写时,只能在本包使用!!!!!!!!!!!!!!!!!!!!
4)函数名大写时,才能跨包使用!!!!!!!!!!!!!!!!!!!!!!!!
8.函数(也是一种数据类型)
8.1golang中的递归函数调用
package main import "fmt" func main() { fn01(5) // 结果依次是2,2,3,4 fmt.Println("================================") fn02(5) // 结果是2 } func fn01(n int) { if n > 2{ n -- fn01(n) } fmt.Println("n的值是:",n) } func fn02(n int) { if n > 2 { n -- fn02(n) }else { fmt.Println("此时n的值是:",n) } }
fn01()的原理图:
fn02()的原理图:
8.2golang函数相关特性:
package main import "fmt" func main() { fmt.Println("1================================") fn01(5) // 结果依次是2,2,3,4 fmt.Println("2================================") fn02(5) // 结果是2 fmt.Println("3================================") i := fn03(7) fmt.Println(i) fmt.Println("4================================") fmt.Println(fn04(2)) fmt.Println("5================================") n := 10 fn05(&n) fmt.Println("n的值是:",n) fmt.Println("6================================") tmp := fn06 fmt.Println(tmp(1,2)) fmt.Println("7================================") tmp01 := fn07(tmp, 5, 2) fmt.Println(tmp01) fmt.Println("9================================") fmt.Println(fn09(1,2,3,4,5)) } // demo01 func fn01(n int) { if n > 2{ n -- fn01(n) } fmt.Println("n的值是:",n) } // demo02 func fn02(n int) { if n > 2 { n -- fn02(n) }else { fmt.Println("此时n的值是:",n) } } // 斐波那契数列 func fn03(n int) (int) { if n == 1 || n == 2 { return 1 } return fn03(n - 1) + fn03(n - 2) } // demo04 func fn04(n int)(int) { if n == 1 { return 3 } return 2 * fn04(n - 1) + 1 } // demo05=================指针类型,引用传递================== func fn05(n *int) { *n = *n + 10 fmt.Println(*n) } // demo06========函数也是一种数据类型===================== func fn06(n1 int, n2 int) (int) { return n1 + n2 } func fn07(fn func(int, int) int, n1 int, n2 int) int { return fn(n1, n2) } // 自定义数据类型 func fn08() { type myInt int var n1 myInt n1 = 80 fmt.Println(n1) } // golang中的可变参 func fn09(n1 int, args... int) (sum int) { sum = n1 for i := 0; i < len(args); i ++{ sum += args[i] } return }
8.3init函数(在main函数之前调用,通常可以在main之前,完成初始化工作)