2019年12月13日10:35:20
1.介绍
2019年10月31日15:09:03
2.基本语法
2.1 定义变量
2019年10月31日16:12:34
1.函数外必须使用var定义变量
var a=1
b:=5
声明变量的一般形式是使用 var 关键字:
var name type
其中,var 是声明变量的关键字,name 是变量名,type 是变量的类型。
2.没有全局变量说法,只有包变量
3.集中定义变量
var (
a int
c string
d bool
)
4.使用var关键字
var a,b,c bool
var s1,s2 string="hello","world"
5.使用:=定义变量
只能在函数体内使用
a,b,c:=1,2,"123"
6.基本类型
Go语言的基本类型有:
bool
string
int、int8、int16、int32、int64
uint、uint8、uint16、uint32、uint64、uintptr
byte // uint8 的别名
rune // int32 的别名 代表一个 Unicode 码
float32、float64
complex64、complex128
7.源代码:
package main
import "fmt"
var (
a int
c string
d bool
)
func main() {
varible()
varibleType()
varibleSimple()
fmt.Println(d)
}
func varible(){
var s int
var t string
fmt.Printf("%d %q\n",s,t)
}
func varibleSimple(){
a,b,c :=1,2,"abc"
b=5
fmt.Println(a,b,c)
}
func varibleType(){
var a,b,c=1,2,"abc"
fmt.Println(a,b,c)
}
2.2 go内建变量类型
2019年10月31日16:26:53
1.复数类型
两种复数类型,分别是 complex64(32 位实数和虚数)类型和 complex128(64 位实数和虚数)类型。
内置的 complex 函数用于构建复数,内建的 real 和 imag 函数分别返回复数的实部和虚部:
var x complex128 = complex(1, 2) // 1+2i
var y complex128 = complex(3, 4) // 3+4i
fmt.Println(x*y) // "(-5+10i)"
fmt.Println(real(x*y)) // "-5"
fmt.Println(imag(x*y)) // "10"
复数使用 re+imi 来表示,其中 re 代表实数部分,im 代表虚数部分,i 代表根号负 1。如果一个浮点数或一个十进制整数后面跟着一个 i,例如 3.141592i 或 2i,它将构成一个复数的虚部,而复数的实部是 0
fmt.Println(1i * 1i) // "(-1+0i)", i^2 = -1
2.强制类型转换
类型转换是强制的
规定是什么类型的参数一定要必须是
返回什么类型也得强转。
3.正弦
正弦函数由 math 包提供,函数入口为 math.Sin,正弦函数的参数为 float64,返回值也是 float64。在使用正弦函数时,根据实际精度可以进行转换。
2.3 常量与枚举
2019年10月31日18:08:39
1.常量
//常量
const s,t=1,2
const y int=5
2.枚举
iota 开始生成枚举值, 默认为0
iota 不仅可以生成每次增加 1 的枚举值。还可以利用 iota 来做一些强大的枚举常量值生成器
//枚举
func enums() {
const(
cpp=iota
java
python
golang
)
//b,kb,mb,gb,tb,pb
const(
b=1<<(10*iota)
kb
mb
gb
tb
pb
)
fmt.Println(cpp,java,python,golang)
fmt.Println(b,kb,mb,gb,tb,pb)
}
3.总结
- 变量类型写在变量名之后
- 编译器可推测变量类型
- 没有char,只有rune
- 原生支持复数类型
2.4 条件语句
2019年10月31日18:24:56
1.if的条件里不需要括号
func varible1() int {
var a int=5
if a>3 {
return 100
}else{
return 122
}
}
2.if的条件里可以赋值
if contents,err:=ioutil.ReadFile(filename); err!=nil{
fmt.Println(err)
}else {
fmt.Println("%s\n", contents)
}
3.switch
func eval(a,b int,op string) int{
var result int
switch op {
case "+":
result = a + b
case "-":
result = a - b
default:
panic("unsupported" + op)
}
return result
}
4.switch会自动break,除非使用fallthrough
5.switch后可以没有表达式
6.源码
package main
import (
"fmt"
"io/ioutil"
)
func main() {
const filename="abc.txt"
//contents,err:=ioutil.ReadFile(filename)
//if err!=nil{
// fmt.Println(err)
//}else {
// fmt.Println("%s\n",contents)
//}
//
//fmt.Println(contents)
if contents,err:=ioutil.ReadFile(filename); err!=nil{
fmt.Println(err)
}else {
fmt.Println("%s\n", contents)
}
fmt.Println(eval(3,1,"+"))
}
func varible1() int {
var a int=5
if a>3 {
return 100
}else{
return 122
}
}
func eval(a,b int,op string) int{
var result int
switch op {
case "+":
result = a + b
case "-":
result = a - b
default:
panic("unsupported" + op)
}
return result
}
2.5 循环
2019年10月31日19:12:25
1.for的条件里不需要括号
//整数转成二进制
func main() {
fmt.Println(
convertToBin(5),
convertToBin(15),
)
}
//循环
func convertToBin(n int) string {
result:=""
for ;n>0;n/=2{
lsb:=n%2
result=strconv.Itoa(lsb)+result
}
return result
}
2.没有while
3.源码
package main
import (
"bufio"
"fmt"
"os"
"strconv"
)
func main() {
fmt.Println(
convertToBin(5),
convertToBin(15),
)
printFile("abc.txt")
}
//循环
func convertToBin(n int) string {
result:=""
for ;n>0;n/=2{
lsb:=n%2
result=strconv.Itoa(lsb)+result
}
return result
}
//读取文本
func printFile(filename string){
file,err:=os.Open(filename)
if err!=nil{
panic(err)
}else{
scanner:=bufio.NewScanner(file)
for scanner.Scan(){
fmt.Println(scanner.Text())
}
}
}
2019年10月31日19:28:28
2.6 函数
2019年10月31日19:28:41
1.函数可以返回多个值
func div(a,b int)(q,r int){
return a/b,a%b
}
func main() {
fmt.Println(123)
div(13,4)
}
2.返回多个值可以起名字
3.没有默认参数,可选参数
4.介绍
函数的基本组成为:关键字 func、函数名、参数列表、返回值、函数体和返回语句,每一个程序都包含很多的函数,函数是基本的代码块。
因为Go语言是编译型语言,所以函数编写的顺序是无关紧要的,
鉴于可读性的需求,最好把 main() 函数写在文件的前面,其他函数按照一定逻辑顺序进行编写(例如函数被调用的顺序)。
2.7 指针
2019年10月31日20:19:48
1.指针不能运算
指针(pointer)在Go语言中可以被拆分为两个核心概念:
- 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。
- 切片,由指向起始元素的原始指针、元素数量和容量组成。
切片比原始指针具备更强大的特性,而且更为安全。切片在发生越界时,运行时会报出宕机,并打出堆栈,而原始指针只会崩溃。
2.go语言只有值传递
3.
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用在变量名前面添加&
ptr := &v // v 的类型为 T
其中 v 代表被取地址的变量,变量 v 的地址使用变量 ptr 进行接收,ptr 的类型为*T
称做 T 的指针类型,*
代表指针。
3.数组切片容器
3.1 数组
2019年10月31日20:37:02
1.定义数组的集中方法
var arr1 [5]int
arr2:=[3]int{1,3,5}
arr3:=[...]int{2,4,6,8,10}
var grid [4][5]int
fmt.Println(arr1,arr2,arr3)
fmt.Println(grid)
2.遍历数组 range
//传统方式
for i:=0;i< len(arr3);i++{
fmt.Println(arr3[i])
}
使用range
for i:=range arr3{
fmt.Println(arr3[i])
}
获得索引和值
for i,v:=range arr3{
fmt.Println(i,v)
}
3.range遍历时索引不想用到
for _,v:=range arr3{
fmt.Println(v)
}
4.为什么用到range
5.数组是值类型
6.[10]int 和[20]int是不同类型
7.调用func f(arr [10]int)会 拷贝 数组
8.go语言一般不直接使用数组
3.2 切片-slice
2019年10月31日20:55:34
1.介绍
切片(slice)是对数组的一个连续片段的引用,所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型)
这个片段可以是整个数组,也可以是由起始和终止索引标识的一些项的子集,需要注意的是,终止索引标识的项不包括在切片内。
切片一般用于快速地操作一块数据集合,如果将数据集合比作切糕的话,切片就是你要的“那一块”,切的过程包含从哪里开始(切片的起始位置)及切多大(切片的大小),容量可以理解为装切片的口袋大小,如下图所示。
2.切片是对数组的视图,同步更新。
//更新视图
func updateArr(arr []int){
arr[0]=1000
}
func main() {
arr3:=[...]int{2,4,6,7,8,5,4,33}
s:=arr3[2:6]
fmt.Println(s)
fmt.Println("arr[:6]= ",arr3[:6])
fmt.Println("arr[2:]= ",arr3[2:])
fmt.Println("arr[:]= ",arr3[:])
s1:=arr3[2:]
s2:=arr3[:]
updateArr(s1)
fmt.Println("更新过的s1:=",s1)
fmt.Println("更新过的arr:=",arr3)
updateArr(s2)
fmt.Println("更新过的s2:=",s2)
fmt.Println("更新过的arr:=",arr3)
}
3.slice本身没有数据,是对底层array的一个view
4.resilce,不断的切片
5.slice扩展
4.为什么用到range
arr:=[...]int{1,2,3,4,5,6,7,8}
fmt.Println("arr:=",arr)
s1:=arr[2:6]
s2:=s1[3:5]
fmt.Printf("s1=%v,len(s1)=%d,cap(s1)=%d\n",s1,len(s1),cap(s1))
fmt.Printf("s2=%v,len(s2)=%d,cap(s2)=%d\n",s2,len(s2),cap(s2))
6.slice实现
7.slice可以向后扩展,不可以向前扩展
8.s[i]不可以超越len(s),向后扩展不可以超越底层数组cap(s)
9.向slice添加元素
s4和s5不再是arr的视图了
s3:= append(s2, 10)
s4:=append(s3,11)
s5:=append(s4,12)
fmt.Println("s3,s4,s5",s3,s4,s5)
fmt.Println("arr:=",arr)
10.添加元素时超越cap,系统会重新分配更大的底层数组
11.由于值传递,必须接受append的返回值
s=append(s,val)
12.定义slice
var s []int
13.知道长度,初始化slice
func printSilce(arr []int){
fmt.Printf("s=%v,len=%d,cap=%d\n",arr,len(arr),cap(arr))
}
func main() {
s1:=[]int{2,4}
printSilce(s1)
s2:=make([]int,16)
s3:=make([]int,16,32)
printSilce(s2)
printSilce(s3)
}
14.copy slice
copy(s2,s1)
15.slice删除某个元素
copy(s2,s1)
printSilce(s2)
s5:=append(s2[:3],s2[4:]...)
printSilce(s5)
16.删除头尾
//删除头尾
front:=s5[0]
s5=s5[1:]
tail:=s5[len(s5)-1]
s5=s5[:len(s5)-1]
fmt.Println(front,tail)
printSilce(s5)
2019年11月01日13:03:18
3.3 map
2019年11月01日13:03:26
1.介绍
Go语言中 map 是一种特殊的数据结构,一种元素对(pair)的无序集合,pair 对应一个 key(索引)和一个 value(值),所以这个结构也称为关联数组或字典,这是一种能够快速寻找值的理想结构,给定 key,就可以迅速找到对应的 value。
2.map建立方式
m:=map[string] string{
"name":"jixi",
"age":"13",
}
m3:=make(map[string]int)
fmt.Println(m,m3)
3.遍历map
for i,v :=range m{
fmt.Println(i,v)
}
4.取得对应key的value
m2:=m["name"]
fmt.Println(m2)
5.删除元素
fmt.Println("_____________删除元素")
delete(m,"name")
fmt.Println(m)
6.判断是否存在key
value,ok:=m[key]
7.除了slice,map,func的内建类型都可以作为key
4.面向对象
4.1 结构体和方法
2019年11月01日13:46:19
1.仅支持封装,不支持继承和多态。
2.go没有class,只有struct
3.不论地址还是结构本身,一律采用.来访问成员
type treeNode struct {
value int
left,right *treeNode
}
func main() {
var root treeNode
root=treeNode{value:3}
root.left=&treeNode{value:10}
root.right=&treeNode{5,nil,nil}
root.right.right=new(treeNode)
fmt.Println(root)
}
4.结构的创建
//工厂函数
func createNode(value int) *treeNode{
return &treeNode{value:value}
}
5.为结构定义方法
//定义方法
func (node treeNode) print() {
fmt.Print(node.value)
}
root.print()
6.方法的不同
不带指针:就是拷贝一份数据,实际上不修改原来的值
带指针:会把地址传过去
//定义方法
func (node treeNode) print() {
fmt.Println(node.value)
}
//带指针
func (node *treeNode) setValue(value int){
node.value=value
}
func main() {
var root treeNode
root=treeNode{value:3}
root.left=&treeNode{value:10}
root.right=&treeNode{5,nil,nil}
root.right.right=new(treeNode)
//fmt.Println(root)
root.print()
root.setValue(200)
root.print()
}
7.源码
node.go
package tree
import "fmt"
type Node struct {
Value int
Left, Right *Node
}
func (node Node) Print() {
fmt.Print(node.Value, " ")
}
func (node *Node) SetValue(value int) {
if node == nil {
fmt.Println("Setting Value to nil " +
"node. Ignored.")
return
}
node.Value = value
}
func CreateNode(value int) *Node {
return &Node{Value: value}
}
traversal.go
package tree
import "fmt"
func (node *Node) Traverse() {
node.TraverseFunc(func(n *Node) {
n.Print()
})
fmt.Println()
}
func (node *Node) TraverseFunc(f func(*Node)) {
if node == nil {
return
}
node.Left.TraverseFunc(f)
f(node)
node.Right.TraverseFunc(f)
}
func (node *Node) TraverseWithChannel() chan *Node {
out := make(chan *Node)
go func() {
node.TraverseFunc(func(node *Node) {
out <- node
})
close(out)
}()
return out
}
entry.go
package main
import (
"fmt"
"imooc.com/ccmouse/learngo/tree"
)
type myTreeNode struct {
node *tree.Node
}
func (myNode *myTreeNode) postOrder() {
if myNode == nil || myNode.node == nil {
return
}
left := myTreeNode{myNode.node.Left}
right := myTreeNode{myNode.node.Right}
left.postOrder()
right.postOrder()
myNode.node.Print()
}
func main() {
var root tree.Node
root = tree.Node{Value: 3}
root.Left = &tree.Node{}
root.Right = &tree.Node{5, nil, nil}
root.Right.Left = new(tree.Node)
root.Left.Right = tree.CreateNode(2)
root.Right.Left.SetValue(4)
fmt.Print("In-order traversal: ")
root.Traverse()
fmt.Print("My own post-order traversal: ")
myRoot := myTreeNode{&root}
myRoot.postOrder()
fmt.Println()
nodeCount := 0
root.TraverseFunc(func(node *tree.Node) {
nodeCount++
})
fmt.Println("Node count:", nodeCount)
c := root.TraverseWithChannel()
maxNodeValue := 0
for node := range c {
if node.Value > maxNodeValue {
maxNodeValue = node.Value
}
}
fmt.Println("Max node value:", maxNodeValue)
}
4.2 包和封装
2019年11月01日14:33:25
封装
1.名字一般使用CamelCase
2.首字母大写: public
3.首字母小写:private
package tree
import "fmt"
type Node struct {
Value int
Left, Right *Node
}
//工厂函数
func createNode(value int) *Node {
return &Node{Value: value}
}
//定义方法
func (node Node) Print() {
fmt.Println(node.Value)
}
//带指针
func (node *Node) SetValue(value int){
node.Value =value
}
package main
import "awesomeProject/src/tree"
func main() {
var root tree.Node
root=tree.Node{Value: 3}
root.Left=&tree.Node{Value: 10}
root.Right=&tree.Node{5,nil,nil}
root.Right.Right=new(tree.Node)
//fmt.Println(root)
root.Print()
root.SetValue(200)
root.Print()
}
4.2 包
4.每个目录一个包
5.main包包含可执行入口
6.为结构定义的方法必须放在同一个包内,但是可以是不同文件
7.封装的好处:
- 隐藏实现细节;
- 可以对数据进行验证,保证数据安全合理。
如何体现封装:
- 对结构体中的属性进行封装;
- 通过方法,包,实现封装。
封装的实现步骤:
- 将结构体、字段的首字母小写;
- 给结构体所在的包提供一个工厂模式的函数,首字母大写,类似一个构造函数;
- 提供一个首字母大写的 Set 方法(类似其它语言的 public),用于对属性判断并赋值;
- 提供一个首字母大写的 Get 方法(类似其它语言的 public),用于获取属性的值。
8.常用内置包
1) fmt
包 fmt 实现了格式化的 I/O 函数,这与 C 的 printf 和 scanf 类似。格式化短语派生于 C 。一些短语(%-序列)这样使用:
2) io
这个包提供了原始的 I/O 操作界面。它主要的任务是对 os 包这样的原始的 I/O 进行封装,增加一些其他相关,使其具有抽象功能用在公共的接口上。
这个包实现了缓冲的 I/O。它封装于 io.Reader 和 io.Writer 对象,创建了另一个对象(Reader 和 Writer)在提供缓冲的同时实现了一些文本 I/O 的功能。
4) sort
sort 包提供了对数组和用户定义集合的原始的排序功能。
strconv 包提供了将字符串转换成基本数据类型,或者从基本数据类型转换为字符串的功能。
6) os
os 包提供了与平台无关的操作系统功能接口。其设计是 Unix 形式的。
sync 包提供了基本的同步原语,例如互斥锁。
8) flag
flag 包实现了命令行解析。
encoding/json 包实现了编码与解码 RFC 4627 定义的 JSON 对象。
10) html/template
数据驱动的模板,用于生成文本输出,例如 HTML。
将模板关联到某个上进行解析。模板内容指向数据结构的元素(通常结构的字段或者 map 的键)控制解析并且决定某个值会被显示。模板扫描结构以便解析,而“游标” @ 决定了当前位置在结构中的值。
11) net/http
net/http 实现了 HTTP 请求、响应和 URL 的解析,并且提供了可扩展的 HTTP 服务和基本的 HTTP 客户端。
unsafe 包包含了 Go 程序中数据类型上所有不安全的操作。通常无须使用这个。
13) reflect
reflect 包实现了运行时反射,允许程序通过抽象类型操作对象。通常用于处理静态类型 interface{} 的值,并且通过 Typeof 解析出其动态类型信息,通常会返回一个有接口类型 Type 的对象。
os/exec 包执行外部命令。
4.3 扩展已有类型
2019年11月01日14:49:06
1.如何扩充系统类型或者别人的类型
- 定义别名
- 使用组合
4.4 gopath
2019年11月01日15:12:38
1.
2.查看gopath
apple$ pwd
/Users/apple/go/src/awesomeProject/src
apple$ echo $GOPATH
/Users/apple/go/src/awesomeProject/src:/Users/apple/go/src/awesomeProject
:/Users/apple/go
apple$ cat ~/.bash_profile
PATH=$PATH:/usr/local/mysql/bin
export GOPATH="/Users/apple/go"
export PATH=$PATH:$GOPATH/bin
export GOROOT=/usr/local/go
3.
2019年12月16日16:51:53
END