博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
golang学习总结
阅读量:5763 次
发布时间:2019-06-18

本文共 16673 字,大约阅读时间需要 55 分钟。

目录

学习golang注意点:

  1. 导的包必须使用;或者使用_未使用的包,作用是调用该包下的初始化方法。
  2. 局部变量声明必须使用。
  3. go语言的包和java的相似,包名.变量访问

1. 初识go语言

1.1 Hello World

package mainimport "fmt"func main() {    fmt.Println("hello world");}

1.2 go 数据类型

布尔:

var a bool = truevar b bool = false

整型:

整型分为有符号和无符号的类型

8, 16 ,32 分别代表位数

int: 根据系统决定是32位还64位

int8: 1个字节,-128~127 相当于java中的short;

int16: 2个字节,-215 ~ 215 -1

int32: 4个字节 -231 ~231 - 1

int64: 8个字节-263 ~263 - 1

uint : .....

无符号整形都是取值0~216 - 1

var a int = -3var b uint = 3 //uint类型不可以为负数

浮点型:

var a float32 = 100.0var b float64 = 100.00 //默认

字符类型

golang中的字符使用的是字节保存的,本质就是一个int32类型

var a byte = 'a'var b byte = 'c'fmt.Print(a, "===", b)  //输出的是该字节对应的字节码: 97===99fmt.Printf("%c === %c", a, b) // a === c

字符串型:

var str string = "hello world"//多行字符串,不需要使用+来连接多行var str2 string = `a         asda asdasdadsadasd `

复数类型:

complex64 是两个float32组成 complex128两个float64组成

var a complex64 = 10 + 3ivar b complex128= 10 + 3i //默认

相关操作

var v= complex(2 , 3) //构造1个复数, a := real(v) //返回复数实部 2b := image(v) 返回复数虚部 3

rune类型:

// rune is an alias for int32 and is equivalent to int32 in all ways. It is// used, by convention, to distinguish character values from integer values.//int32的别名,几乎在所有方面等同于int32//它用来区分字符值和整数值type rune = int32

1.3 变量常量

局部变量:

属于函数或者方法;声明之后必须使用

var a = 3;var b int = 3;c := 3

全局变量

b := 10 这种全局变量声明是错误的

全局变量的概念:隶属于,声明之后可以不使用

var a intvar (    c int    d string)var e = 3

常量

局部

const a = 3

全局

const a int = 10const b  = 20const (    d int = 10    e string = "ss"    f = 30)

1.5 字符串相关操作

golang中string底层是通过byte数组实现的,byte使用utf-8编码标识的Unicode文本,每个汉字占3个字节

  1. 求长度
func strDemo() {    fmt.Println(len("hello")) //5    fmt.Println(len("中")) //3    fmt.Println(len([]rune("中"))) //1, 正确获取中文字符串长度}
  1. 字符串遍历
//对中文无法支持func strEach() {    str := "hello world"    for i := 0; i < len(str); i ++ {        //fmt.Print(str[i] ,"\t") // 104    101 108 108 111 32  119 111 114 108 100        //讲字节编码转为字符串输出        fmt.Printf("%c\t", str[i]) //h  e   l   l   o       w   o   r   l   d    }}
func strEach() {    str := "hello world 中国"    for i, s := range str {         //0    h1  e2  l3  l4  o5   6  w7  o8  r9  l10 d11  12 中15 国        fmt.Print(i, "\t", string(s))    }}//这个可以正确的输出索引func strEachRune() {    str := "中国人民"    for i, s := range []rune(str) {        fmt.Println(i, string(s))    }}
  1. 其他操作
str := "中国人民, hello world"index := strings.Index(str, "国") //存在则 index > -1, 否则 == -1   此时index=-3split := strings.Split(str, ",")replace := strings.Replace(str, "o", "2", 1) //第三个参数标识替换几个,小于0,则替换所有result := strings.EqualFold("中国", "中国2") //不区分大小写fmt.Println("中国" == "中国H") //区分大小写, 同strings.Compare()5

1.6 相互转换

1.6.1 基本数据

golang基本数据数据之间的转换可使用公:T(i) 进行相互转换

//数据之间的相互转换func transfer() {    //    var i int = 10    var j float64 = 11.30    x := float64(i)    y := int(j)    fmt.Print(x, "\t", y) //10  11}

1.6.2 string <=> 基本数据类型

  1. 基本类型=>string

fmt.Sprintf(format string, param interface{})

func stringTrans() {    var i int = 10    var flag bool = true    int_str := fmt.Sprintf("%d", i)    bool_str := fmt.Sprintf("%t", flag)    fmt.Println(int_str)    fmt.Println(bool_str)}

strconv

func stringStrco() {    var i int = 10000    var flag bool = true    var price float64 = 130.32    formatInt := strconv.FormatInt(int64(i), 10) //等价: strconv.Itoa(i)    formatBool := strconv.FormatBool(flag)    formatFloat := strconv.FormatFloat(price, 'f', 10, 64)    fmt.Println(formatInt)    fmt.Println(formatBool)    fmt.Println(formatFloat)}
  1. String=>基本数据类型
func strToBase() {    str_flag := "true"    str_age := "20"    str_price := "20.33"    flag, _ := strconv.ParseBool(str_flag)    age, _ := strconv.ParseInt(str_age, 10, 64)    age_int, _ := strconv.Atoi(str_age)    price, _ := strconv.ParseFloat(str_price, 64)    fmt.Println(flag)    fmt.Println(age)    fmt.Println(price)    fmt.Println(age_int)}

1.6.3 字节数组和字符串

func byteAndStr() {    str := "hello world, 中国"    data := []byte(str)    s := string(data)    fmt.Println(s)    fmt.Println(data)}

1.7 时间

  1. 获取时间
func timeOperate() {    cur := time.Now()    curT := time.Now().Unix() //获取时间戳    fmt.Println(cur) //2019-01-30 20:40:16.410689 +0800 CST m=+0.000353772    fmt.Println(curT) //1548852137}
  1. 时间和字符串转换
func formatTime() {    format := time.Now().Format("2006-01-02 15:04:05")    //时间戳转时间    var timestamp int64 = 1548852137    unix := time.Unix(timestamp, 0).Format("2006-01-02 15:04:05")    //字符串转时间    formatTimeStr := "2017-04-11 13:33:37"    strToTime, _ := time.Parse("2006-01-02 15:04:05", formatTimeStr)    fmt.Println(format) //2019-01-30 21:00:53    fmt.Println(unix)    fmt.Println(strToTime) //2017-04-11 13:33:37 +0000 UTC}

1.8 复合数据类型

数组和切片(slice)之间的区别:

​ 数组:声明的时候必须指定长度var arr [10]int,值类型,但是在java里面数组是引用类型

​ Slice: 长度可变,不需要指定长度,引用类型

1. 数组

//数组的声明func createArray() {    var books [3]string    books[0] = "java"    books[1] = "python"    books[2] = "golang"    names := [3]string{"lisi", "zhansan", "hand"}    scores := [...]int{89, 59, 30, 100} //根据后面的内容决定长度    fmt.Println(books)    fmt.Println(names)    fmt.Println(scores)}//数组的相关操作func operateArray() {    //数组长度    scores := [...]int{89, 59, 30, 100}    fmt.Println(len(scores))    //数组遍历    for i := 0; i < len(scores); i++ {        fmt.Print(scores[i], "\t")    }    fmt.Println()    for index, value := range scores {        fmt.Print(index, "==", value, "\t")    }}

2. slice

slice是一个比较复杂的数据结构,也就相当于Java里面集合的概念,是一个可变长的数据

//最简单的一种声明方式func createSlice() {    var args []int    args = make([]int, 10)    args[0] = 1    args[1] = 2    args[2] = 3    args[3] = 4    args[4] = 5    for index, value := range args {        fmt.Println(index, value)    }}

通过数组定义一个切片

len 切片长度, 表示当前切片元素的个数

cap切片容量,表示切片可以容纳切片的个数,如果超出则报错

func createSlice2() {    arrays := [...]int{1, 2, 3, 4, 5}    slice := arrays[1:4] //[2 3 4]    fmt.Println(len(slice)) //3    fmt.Println(cap(slice)) //4    slice[1] = 10    //这里可以解释下图    fmt.Println(arrays) //[1 2 10 4 5]    fmt.Println(slice) // [2 10 4]}

这里容量为什么是4?,如图

1202755-20190207205314371-1218755546.png

append&copy函数

当append超出原来容量的时候,会扩展原来的容量为原先的两倍

//appendfunc appendFunc() {    slice := make([]int, 2, 4)    slice[0] = 1    slice[1] = 1    slice = append(slice, 2)    slice = append(slice, 3)    slice = append(slice, 4)    fmt.Println(len(slice)) //5    fmt.Println(cap(slice)) //8}//copy函数的用法func copyFunc() {    slice := make([]int, 2, 4)    slice2 := make([]int, 2, 4)    slice[0] = 1    slice[1] = 1    copy(slice2, slice) //相当于 slice2 := slice[:]    fmt.Println(slice2) // [1 1]}

3. map

map 数据结构和java的HashMap类似。

//创建一个mapfunc createMap() {    var product map[string]interface{} //声明    product = make(map[string]interface{}) //初始化    product["id"] = 1    product["title"] = "口红"    product["price"] = 199.33    fmt.Println(product)}//遍历mapfunc mapForEach() {    var product map[string]interface{} //声明    product = make(map[string]interface{}) //初始化    product["id"] = 1    product["title"] = "口红"    product["price"] = 199.33    for key, value := range product {        fmt.Println(key, value)    }}

1.9 golang面向对象

1. 结构体

go语言中的结构体和Java中的类很相似,包含属性,方法等内容。首字母大写对其他包可见,首字母小写只是对本包可见。

指针和值类型: 指针类型的方法可以修改属性的值,值类型的不可以修改,

package mainimport "fmt"func main() {    student := &Student{"zhansn", 24}    fmt.Println(student.GetName())//zhansn    student.SetName("lisi")    fmt.Println(student.GetName()) //lisi}//对属性小写可以封装type Student struct {    name string    age int}//定义结构体的方法GetName和SetNamefunc (this Student) GetName() string {    return this.name}//这里使用指针可以改变属性的内容func (this *Student) SetName(name string) {    this.name = name}

2. 继承

在go语言中结构体和结构体没有继承,而是通过组合的方式来获取其他结构体的方法。此时的Student可以使用Person的所有属性和方法,无论是否封装。

package mainimport "fmt"func main() {    student := &Student{}    fmt.Println(student.GetName()) // ""    student.SetName("lisi")    fmt.Println(student.GetName()) //lisi}//对属性小写可以封装type Student struct {    Person}type Person struct {    name string    age int}//定义类型的方法func (this Person) GetName() string {    return this.name}//这里使用指针可以改变属性的内容func (this *Person) SetName(name string) {    this.name = name}

3. 接口

golang接口中没有变量,只有方法。

对于java中的多态描述:重载和重写两种多态。但是在golang中无法对方法进行重载,因为golang是一门面向函数编程的语言。所以golang可以通过重写来实现多态,而且是接口和子类之间的重写。

package mainimport "fmt"func main() {    ben := &Ben{"benchi"}    ao := &Ao{"aodi"}    ToString(ben)    ToString(ao)}type Car interface {    GetName() string    SetName(name string)}func ToString(car Car) {    fmt.Println(car.GetName())}type Ben struct {    name string}func (ben Ben) GetName() string {    return ben.name}func (ben *Ben) SetName(name string) {    ben.name = name}type Ao struct {    name string}func (this Ao) GetName() string {    return this.name}func (this *Ao) SetName(name string) {    this.name = name}

4. 类型断言

golang 类型断言和java中的instanceof 关键字相似,但是又比这个关键字高级,好用,实现方式val.(T)

func main() {    var x interface{}    x = 4    if y, ok := x.(int); ok {        fmt.Println(y)    }}

断言接口子类

package mainimport "fmt"func main() {    ben := Ben{"benchi"}    ao := Ao{"aodi"}    ToString(ben)    ToString(ao)}type Car interface {    GetName() string}func ToString(car Car) {    if ben, ok := car.(Ben); ok {        fmt.Println(ben.GetName())    } else if ao, ok := car.(Ao); ok {        fmt.Println(ao.GetName())    } else {        fmt.Println("other type")    }}type Ben struct {    name string}func (ben Ben) GetName() string {    return ben.name}type Ao struct {    name string}func (this Ao) GetName() string {    return this.name}

如下代码,有什么问题呢?此时我们使用指针类型是实现了接口notify的方法,那么在SendNotify(u notify)中我们必须使用子类的指针作为参数传递到该函数,如果我们使用值类型实现接口notify的方法,例如func (this user) Notify()这样既可以使用指针也可以使用值传递参数。

package mainimport "fmt"func main() {    u := &user{"hello"} //此时必须传递指针参数    SendNotify(u)}type notify interface {    Notify()}type user struct {    name string}//指针实现接口func (this *user) Notify() {    fmt.Println(this.name)}func SendNotify(u notify) {    u.Notify()}

这是为什么呢?

对于一个方法method(param T) 可以接受值类型指针类型的参数,method(param *T) 仅仅可以接受指针类型的参数。

5. 闭包

java中有函数式编程,集合框架中有一个消费型函数forEach,我们在golang中通过闭包实现该函数

package mainimport "fmt"func main() {    data := []int{1,2,3,4,5}    forEach(data, func(index int, value interface{}) {        fmt.Println(index, value)    })}func forEach(data []int, f func(int, interface{})) {    for index, value := range data {        f(index, value)    }}

2. golang 杂项

2.0 defer

defer会在函数或者方法结束前被调用,和Java中finally相似

func main() {    /**    first    hello world    defer is called     */    say()}func say() {    fmt.Println("first")    defer fmt.Println("defer is called")    fmt.Println("hello world")}//由于return了,所以return后面的语句不会被执行func say2() {    fmt.Println("first")    return    defer fmt.Println("defer is called")    fmt.Println("hello world")}

defer使用场景:错误处理,关闭资源,释放锁,后续会见到这些使用操作

2.1 错误处理

这里诉说的错误处理和Java中的异常处理一样,在java语言中错误处理一般都是try...catch…finally,而在golang语言中通过三个关键字对错误尽心处理:(defer recover) panic

  1. defer+recover来捕获异常
func catchError() {    defer func() {        err := recover()        if err != nil {            fmt.Println("出现异常", err)        }    }()    a := 10    b := 0    x := a / b    fmt.Println(x)}
  1. 自定义异常
func catchError() {    //在这里捕获处理,如果不进行捕获,则程序会崩溃    defer func() {        err := recover()        if err != nil {            fmt.Println("出现异常", err)        }    }()    err := selfError()    //向外抛出异常    panic(err)}func selfError() error {    return errors.New("自定义异常")}

2.2 日志

package mainimport "log"func main() {    //  info:2019/02/04 16:47:25 LoggerDemo.go:6: message    log.Println("message")}func init() {    log.SetPrefix("info:")    log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)}
func main() {    log.Println("message")    //Fatalln执行之后调用:os.Exit(1), 退出程序,后续程序不再执行    log.Fatalln("打印日志,程序退出")    fmt.Println("还会执行吗")}

定制日志记录器

package loggerimport (    "log"    "os"    "io")var (    Debug *log.Logger  //仅仅输出到控制台    Info *log.Logger    Warning *log.Logger    Error *log.Logger)const (    logFlag = log.LstdFlags | log.Lshortfile)func init() {    file, error := os.OpenFile("info.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)    if error != nil {        panic(error)    }    Debug = log.New(os.Stdout, "debug:", logFlag)    Info = log.New(io.MultiWriter(file, os.Stdout), "info:", logFlag)    Warning = log.New(os.Stdout, "waring:", logFlag)    Error = log.New(io.MultiWriter(file, os.Stderr), "error:", logFlag)}

测试

package mainimport "logger"func main() {    logger.Debug.Println("debug")    logger.Info.Println("create a info log")    logger.Error.Println("create a errr log")}

2.3 IO流

package mainimport (    "os"    "fmt"    "bufio"    "io"    "io/ioutil")func openFile() {    file, err := os.Open("info.log")    if err != nil {        fmt.Println("文件错误", err)    }    defer file.Close()    reader := bufio.NewReader(file)    for {        str, err := reader.ReadString('\n')        if err == io.EOF { //表示读取完毕            break        }        fmt.Print(str)    }}//读取内容到内存中func openFile2() {    data, err := ioutil.ReadFile("info.log")    if err != nil {    }    fmt.Print(string(data))}func writeFile() {    file, err := os.OpenFile("hello.txt", os.O_WRONLY| os.O_CREATE | os.O_APPEND, 0666)    if err != nil {        fmt.Println("创建文件错误")        return    }    defer file.Close()    writer := bufio.NewWriter(file)    for i := 0; i < 5; i++ {        writer.WriteString("写入数据:\n")    }    writer.Flush() //将缓冲区内容写入到文件中}//判断文件是否存在func IsExist() {    _, e := os.Stat("info2.log")    if e != nil {        exist := os.IsNotExist(e)        fmt.Println(exist)    }}

2.5 json

package mainimport (    "encoding/json"    "fmt"    "time")type Book struct {    Title string    Author string    Publish time.Time}//序列化mapfunc serializeMap() {    student := make(map[string]interface{})    student["name"] = "闰土"    student["age"] = 20    student["class"] = "大一"    bytes, err := json.Marshal(student)    if err != nil {        fmt.Println("序列化错误")    }    fmt.Println(string(bytes)) //{"age":20,"class":"大一","name":"闰土"}}//序列化结构体func serializeStruct() {    book := Book{"青春","itcloud", time.Now()}    bytes, _ := json.Marshal(book)    fmt.Println(string(bytes)) // {"Title":"青春","Author":"itcloud","Publish":"2019-02-05T11:14:51.094709+08:00"}}func deserializeMap() {    var student map[string]interface{}    data := `{"age":20,"class":"大一","name":"闰土"}`    err := json.Unmarshal([]byte(data), &student)    if err != nil {}    fmt.Println(student)}func deserializeStruct() {    var book Book    bookStr := `{"Title":"青春","Author":"itcloud","Publish":"2019-02-05T11:14:51.094709+08:00"}`    json.Unmarshal([]byte(bookStr), &book)    fmt.Println(book)}

2.6 网络编程

1. TCP

客户端

package mainimport (    "bufio"    "fmt"    "net"    "os")func main() {    conn, _ := net.Dial("tcp", "127.0.0.1:8088")    reader := bufio.NewReader(os.Stdin)    line, _ := reader.ReadString('\n')    n, _ := conn.Write([]byte(line))    fmt.Println(n)}

服务端

package mainimport (    "fmt"    "net")func main() {    listener, err := net.Listen("tcp", "127.0.0.1:8088")    if flag := Checkout(err, "监听开启错误"); !flag {        return    }    defer listener.Close()    for {        fmt.Println("等待客户端建立连接...")        conn, err := listener.Accept()        if flag :=  Checkout(err, "打开连接失败"); flag {            fmt.Printf("conn= %v, ip = %v\n", conn, conn.RemoteAddr().String())        }        go process(conn)    }}func process (conn net.Conn) {    defer conn.Close()    for {        buf := make([]byte, 1024)        readLen, err := conn.Read(buf)        if flag := Checkout(err, "读取失败"); !flag {            return        }        fmt.Println(string(buf[:readLen]))    }}func Checkout(err error, msg string) bool {    if err != nil {        fmt.Println(msg, err)        return false    }    return true}

2. http

func main() {    http.HandleFunc("/echo", echo)    http.ListenAndServe(":8080", nil)}func echo(w http.ResponseWriter, r *http.Request) {    body, err := ioutil.ReadAll(r.Body)    if err != nil {        w.Write([]byte("get body error"))        return    }    strlen, err := w.Write(body)    if err != nil && strlen != len(body) {        w.Write([]byte("write a error"))    }}
package mainimport (    "net/http"    "time")//自定义handlerfunc main() {    myHandler := &SelfHandle{format: time.RFC1123}    http.Handle("/time", myHandler)    http.ListenAndServe(":8080", nil)}type SelfHandle struct {    format string}func (h *SelfHandle) ServeHTTP(w http.ResponseWriter,  r *http.Request) {    forTime := time.Now().Format(h.format)    w.Write([]byte("time is " + forTime))}

多路复用处理器

package mainimport "net/http"//多路复用处理器func main() {    mux := http.NewServeMux()    mux.HandleFunc("/hello", hello)    mux.HandleFunc("/world", world)    server := &http.Server{Addr: ":8080", Handler: mux}    server.ListenAndServe()}func hello(w http.ResponseWriter, r *http.Request) {    w.Write([]byte("hello"))}func world(w http.ResponseWriter, r *http.Request) {    w.Write([]byte("word"))}

转载于:https://www.cnblogs.com/hu1056043921/p/10312072.html

你可能感兴趣的文章
lamp+nginx代理+discuz+wordpress+phpmyadmin搭建一
查看>>
nagios监控使用139邮箱报警
查看>>
Windows Phone 7 中各种Task解说(启动器与选择器)
查看>>
罗森伯格助力2011年中国智能建筑技术发展应用论坛哈尔滨站
查看>>
windows server 2016 活动目录(二)
查看>>
openstack G版 修改vm的flavor级别
查看>>
python_控制台输出带颜色的文字方法
查看>>
java泛型中特殊符号的含义
查看>>
Android组件化最佳实践 ARetrofit原理
查看>>
舍弃浮躁, 50条重要的C++学习建议
查看>>
同步手绘板——将View的内容映射成Bitmap转图片导出
查看>>
【Android游戏开发之十】(优化处理)详细剖析Android Traceview 效率检视工具!分析程序运行速度!并讲解两种创建SDcard方式!...
查看>>
微信小程序之wx.navigateback往回携带参数
查看>>
陌陌和请吃饭之类的应用,你要是能玩转,那就厉害了
查看>>
递归的运行机制简单理解
查看>>
汉字转阿斯克马值
查看>>
Java 栈与堆简介
查看>>
【supervisord】部署单进程服务的利器
查看>>
zabbix oracle监控插件orabbix部署安装
查看>>
python3 通过qq 服务器 发送邮件
查看>>