1.变量定义
var a int = 1 // var a,b,c =1,"2",4
编译器可以自动识别类型
a,b := 1,2(只能初次定义使用,包外部不可用)
var (
a = '1'
)
2.内建变量类型
bool、string
无符号:(u)int,(u)int8,(u)int16,(u)int32,(u)int64,uintptr 指针
byte(8位),rune (字符型)32位
float32,float64,complex64(复数,实部和虚部分别是32位)、complex128(复数,实部和虚部64位)
复数:
欧拉公式:
常量
const a,b = 3,5
var c = int
fmt.Print(int(math.Sqrt(a*b+c+d)))
枚举类型:
go语言没有特殊的枚举关键字,所以用一组const来定义表示
普通枚举:
const(
cpp =0
java = 1
py = 2
)
自增枚举:
const(
cpp = iota //自增值
java
py
)
复杂运算:
//b,kb,mb,gb,tb,pb
const(
b = 1<<(10*iota)
kb
mb
gb
)
可以作为一个自增值的种子
判断语句 if
if content,err := ioutil.ReadFile(filename);err=null{
fmt.PrintIn(string(content))
}else{
fmt=PrintIn("content is err",err)
}
switch
func grade(score int)string{
g := ""
switch{
case score<0||score>100:
panic(fmt.Sprint("Wrong scroe : %d", score))
case score < 60:
g = "F"
case score< 80:
g ="C"
}
return g
}
go语言的switch自带berak
for
for ; ; {}
func printFile(){
filname := "123.txt"
file,err := os.Open(filename)
if err!=nill{
panic(err)
}
scanner=bufio.NewScanner(file)
for scanner.Scan(){
fmt.PrintIn(scanner.Text())
}
}
指针
var a int =2
var pa *int =&a
*pa =3
指针不能运算
Go语言只有值传递一种方式
当 func f(pa *int)的时候,相当于把地址进行传递
当 func f(cache Cache)的时候,相当于直接把cache里面pDate指针拷贝过去,都是指向data
func swap(a,b *int){
*b,*a=*a,*b
}
swap(&a,&b)
数组:
var arr1 [3][4]int
arr2 :=[4]int {3,4,5,6}
arr3 :=[...]int{123,23,4,5}
var arrs [3][4] int
数组遍历:
for i:=range arr3{ //for i/_,v :=range arr3
fmt.PrintIn(arr3[i])
}
i是数组下标,v为值 类似于foreach
数组是值类型
[10]int 和[20]int 是不同类型
调用func f(arr [10]int)会拷贝数组
在go语言不直接使用数组,而使用切片
切片:
slice本身是没有数据的,是对底层array的一个视图
实例:
arr := [...]int{0,2,3,4,5,6}
fmt.Println(arr[2:6],arr[:6],arr[2:],arr[:])
还可以resilic
s:=arr[2:6]
s = s[:3]
s=s[1:]
s=arr[:] //和指针相同
slice的扩展:
问题一:
arr:=[...]int{0,1,2,3,4,5,6}
s1:=arr[2,6]
s2:=s1[3:5]
s1=[2,3,4,5] s2=[5,6]
cap=cap(s1)
添加元素如果超过cap,系统会重新分配更大的底层数组
由于值传递的关系,必须接受append的返回值
s=append(s,val)
var s []int //zero value for slice is nil
s = append(s,2*i+1)//当cap每次装不下的时候会*2
还可以这样创建:
s2 :=make([]int,16) //len=6
s3 :=make([]int,10,32) //len=10,cap=32
copy: copy (s2,s1) //把s1拷贝到s2
del:中间的下标3的元素: s2=append(s2[:3],s2[4:]...)
从头和从尾去掉:
front :=s2[0]
s2=s2[1:]
tail := s2[len(s2)-1]
s2=s2[:len(s2)-1]
如果创建一个长度为16的slice:
s2 := make([]int,16)
创建一个有10个元素,但是数组有32个长度
s3 :=make([]int,10,32)
删除下标为3的元素
s2=append(s2[:3],s2[4:]...)
len会改变,cap不会改变
删除首尾:
s2=s2[1:]
s2=sw[:len(s2)-1 ]
Map:
map[K]V,map[K1]map[K2]V
声明实例:
创建:
map := map[string]string{
"name":"123",
}
var m2 map[string] int //m2=nil
m3 :=make(map[string]int) //m3=empty map
遍历:k在map中是无序的,是hash map,需要给key进行排序,把key取出来放到slice中,排序完再去遍历map
for k,v/_,v/k :=range m{
}
取值:
if name,ok:=m["name"];ok{
fmt.Println(name,ok)
}else{
fmt.Println(name,ok)
}
删除:
delete(m,"name")
map的key:
1>map使用哈希表,必须可以比较相等
2>除了slice,map,function的内建类型都可以作为key
3>Struct类型不包括上述字段也可以作为key
面向对象
go语言仅支持封装,不支持继承和多态,没有class只有struct
创建结构体:
type treeNode struct{
value int
left,right *treeNode
}
func (node treeNode) print(){ //treeNode结构体内的方法,go语言都是传值的
fmt.Println(node.value)
}
实例化:
root :=treeNode{}
root.left=&treeNode{}
root.right.left=new(treeNode)
nodes:=[]treeNode{
{value:2}
{}
{1,nil,nil},
}
工厂函数:
funct createNode(value int )*treeNode{
return &treeNode{value:value} //返回局部变量的地址
}
接口:
go语言是面向接口的编程语言,没有继承和多态,通过接口完成
duck typing:描述事务的外部行为而非内部结构
严格说go属于结构化类型系统,类似duck typing
go语言的接口是由使用者定义
接口类:
type Retriever interface {
Get(url string) string //在interface中不用加func
}
func download(r Retriever) string{ //使用者
return r.Get("http://www.imooc.com")
}
func main() {
var r Retriever
r=mock.Retrievers{"this is a fake imooc.com"}
//r=mock.Retrievers{"this is a fake imooc.com"}
r=real.Retriever{}
fmt.Println(download(r))
//fmt.Println(download(r))
}
实现类:
type Retriever struct {
UserAgent string
TimeOut time.Duration
}
func(r Retriever) Get(url string) string{
resp,err:=http.Get(url)
if err!=nil{
panic(err)
}
result,err:=httputil.DumpResponse(resp,true)
resp.Body.Close()
if err!=nil{
panic(err)
}
return string(result)
}
在r的里面有两个内容,一个类型,一个值
func inspect(r Retriever){
fmt.Printf("%T %v\n",r,r)
//第二种打印方式
switch v:=r.(type) {
case mock.Retrievers:
fmt.Println("content:",v.Contentst)
case *real.Retriever:
fmt.Println("UserAgent:",v.UserAgent)
}
}
func main() {
var r Retriever
inspect(r)
r=mock.Retrievers{"this is a fake imooc.com"}
//r=mock.Retrievers{"this is a fake imooc.com"}
inspect(r)
r=&real.Retriever{UserAgent:"Mozilla/5.0",TimeOut:time.Minute}
//fmt.Printf("%T %v\n",r,r) 第一种打印方式
inspect(r)
//fmt.Println(download(r))
//fmt.Println(download(r))
//第三种打印方式
realRetriever := r.(*real.Retriever)
fmt.Println(realRetriever.TimeOut)
if mockRetriever,ok:=r.(mock.Retrievers);ok{
fmt.Println(mockRetriever.Contentst)
}else{
fmt.Println("not a mock retriever")
}
}
接口变量里面有:实现者的类型、实现者的值(或者是实现者的指针指向实现者)
接口变量自带指针,接口变量统一采用值传递,几乎不需要使用接口的指针
指针接受者实现只能以指针方式使用,值接收者都可以
func的返回类型如果是interface的话不限制返回类型,但是可以在返回值时添加类型限制,比如 return head.(int )
常用的接口:
string:
func (r *Retrievers)String()string{
return fmt.Sprintf(
"Retriever:{Contents=%s}",r.Contentst)
}
Read:实现的人读取文件给你的[]byte里面
Write:写入到文件里面
函数式编程:
函数是一等公民:参数,变量,返回值都可以是函数
高阶函数:函数的参数也可以是函数
func adder() func(int)int{
sum:=0
fmt.Println(sum)
return func(v int) int {
sum+=v
return sum
}
}
func main() {
a:=adder()
fmt.Println("............")
for i:=0;i<10;i++{
fmt.Println(a(i))
}
}