2019年12月13日10:35:20

1.介绍

2019年10月31日15:09:03

16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP

2.基本语法

2.1 定义变量

2019年10月31日16:12:34

1.函数外必须使用var定义变量

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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.总结

  1. 变量类型写在变量名之后
  2. 编译器可推测变量类型
  3. 没有char,只有rune
  4. 原生支持复数类型

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后可以没有表达式

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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语言只有值传递

16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP

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)

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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)
}

16.go语言基础学习(上)——2019年12月16日-LMLPHP

3.range遍历时索引不想用到

	for _,v:=range arr3{
fmt.Println(v)
}

4.为什么用到range

16.go语言基础学习(上)——2019年12月16日-LMLPHP

5.数组是值类型

6.[10]int 和[20]int是不同类型

7.调用func f(arr [10]int)会 拷贝 数组

8.go语言一般不直接使用数组

3.2 切片-slice

2019年10月31日20:55:34

16.go语言基础学习(上)——2019年12月16日-LMLPHP

1.介绍

切片(slice)是对数组的一个连续片段的引用,所以切片是一个引用类型(因此更类似于 C/C++ 中的数组类型,或者 Python 中的 list 类型)

这个片段可以是整个数组,也可以是由起始和终止索引标识的一些项的子集,需要注意的是,终止索引标识的项不包括在切片内。

切片一般用于快速地操作一块数据集合,如果将数据集合比作切糕的话,切片就是你要的“那一块”,切的过程包含从哪里开始(切片的起始位置)及切多大(切片的大小),容量可以理解为装切片的口袋大小,如下图所示。

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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) }

16.go语言基础学习(上)——2019年12月16日-LMLPHP

3.slice本身没有数据,是对底层array的一个view

4.resilce,不断的切片

5.slice扩展

4.为什么用到range

16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP

	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))

16.go语言基础学习(上)——2019年12月16日-LMLPHP

6.slice实现

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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)

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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) }

16.go语言基础学习(上)——2019年12月16日-LMLPHP

14.copy slice

copy(s2,s1)

15.slice删除某个元素

	copy(s2,s1)

	printSilce(s2)

	s5:=append(s2[:3],s2[4:]...)
printSilce(s5)

16.go语言基础学习(上)——2019年12月16日-LMLPHP

16.删除头尾

	//删除头尾
front:=s5[0]
s5=s5[1:] tail:=s5[len(s5)-1]
s5=s5[:len(s5)-1] fmt.Println(front,tail) printSilce(s5)

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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)

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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.结构的创建

16.go语言基础学习(上)——2019年12月16日-LMLPHP

//工厂函数
func createNode(value int) *treeNode{
return &treeNode{value:value}
}

5.为结构定义方法

16.go语言基础学习(上)——2019年12月16日-LMLPHP

//定义方法
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()
}

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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.

16.go语言基础学习(上)——2019年12月16日-LMLPHP

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.

16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP
16.go语言基础学习(上)——2019年12月16日-LMLPHP

2019年12月16日16:51:53

END

04-19 21:20