Go语法速览

Go语法速览

字符串

package main

import (
    "bytes"
    "fmt"
)

func main() {
    var buffer bytes.Buffer
    for i := 0; i < 1000; i++ {
        buffer.WriteString("a")
    }
    fmt.Println(buffer.String())
}

指针数组

package main

import (
    "fmt"
)

const MAX int = 3

func main() {
    //数组
    a := []int{10, 100, 200}
    //指针数组
    var ptr [MAX]*int
    for i := 0; i < MAX; i++ {
        ptr[i] = &a[i] /* 整数地址赋值给指针数组 */
    }
    //*((&ptr)[0]) = 1
    *ptr[0] = 1
    for i := 0; i < MAX; i++ {
        fmt.Printf("a[%d] = %d\n", i, a[i])
        fmt.Printf("a[%d] = %d\n", i, *ptr[i])
    }
}
package main

import "fmt"

func main() {
    array := [5]*int{1: new(int), 3: new(int)}
    array[0] = new(int)
    *array[0] = 2
    doubleNum(array)
    fmt.Println(*array[0])
}
//函数间传递数组
func doubleNum(arr [5]*int) {
    for k, v := range arr {
        fmt.Println(k, v)
        if v != nil {
            fmt.Println(k, *v)
        }
    }
}

结构体

package main

import (
    "fmt"
    "strconv"
)

type Book struct {
    id   int
    name string
    //嵌入类型
    user
    desc string
}
type user struct {
    id    int
    name  string
    email string
}

func main() {
    //忽略的字段为 0 或 空, author={}
    cBook := Book{name: "C语言"}
    cBook.id = 1002
    bookInfo(cBook)
    //不能忽略字段
    gBook := Book{1001, "go语言", user{id: 2001, name: "andy", email: "[email protected]"}, ""}
    //new它只接受一个参数,这个参数是一个类型,分配好内存后,返回一个指向该类型内存地址的指针。
    //同时请注意它同时把分配的内存置为零,也就是类型的零值。
    u := new(user)
    u.name = "jon"
    u.email = "[email protected]"
    gBook.changeBookAuthor(*u)
    bookInfo(gBook)
    //嵌入类型可以用外部类型直接访问,也可以通过内部类型进行访问
    fmt.Println(gBook.email)
    log(gBook)
}

func bookInfo(book Book) {
    fmt.Printf("id=%d,name=%s,author=%s,des=%s\n", book.id, book.name, book.user, book.desc)
}

//定义bo的类型是指针*Book,才会改变它的值
//如果bo的类型是Book,不会改变它的值
func (bo *Book) changeBookAuthor(user user) {
    bo.user = user
    bo.desc = "change user"
}

//如果内部类型实现了某个接口,那么外部类型也被认为实现了这个接口
type logger interface {
    printLog()
}

func (u user) printLog() {
    fmt.Println(strconv.Itoa(u.id) + "--" + u.name)
}

func log(logger logger) {
    logger.printLog()
}

切片

package main

import "fmt"

func main() {
    //slice:=make([]int,5,10)
    slice := []int{1, 2, 3, 4, 5}
    //切片slice[i:j] 长度:j-i 容量:k-i
    newSlice := slice[1:3]
    sliceInfo(newSlice)
    newSlice = append(newSlice, 101)
    sliceInfo(newSlice) //[2,3,101]
    sliceInfo(slice)    //slice = [1,2,3,101,5]

    //修改一个索引的值后,发现原切片的值也被修改了,说明它们共用一个底层数组。
    modify(slice)
    sliceInfo(slice) //[1,10,3,101,5]
}

func sliceInfo(s []int) {
    fmt.Printf("slice 长度:%d,容量:%d\n", len(s), cap(s))
    for k, v := range s {
        fmt.Println(k, "--", v)
    }
}

func modify(slice []int) {
    fmt.Printf("%p\n", &slice)
    slice[1] = 10
}

一般我们在创建新切片的时候,最好要让新切片的长度和容量一样,这样我们在追加操作的时候就会生成新的底层数组,和原有数组分离,就不会因为共用底层数组而引起奇怪问题,因为共用数组的时候修改内容,会影响多个切片。

package main

import "fmt"

func main() {
    slice := make([]int, 4, 4)
    slice[0] = 1
    slice[1] = 2
    newSlice := slice[1:3:3] //长度是2;容量是2
    sliceInfo(newSlice)      //[2,0]
    newSlice = append(newSlice, 101)
    sliceInfo(newSlice) //[2,0,101]
    sliceInfo(slice)    //[1,2,0,0]
}

func sliceInfo(s []int) {
    for i := 0; i < len(s); i++ {
        fmt.Print(s[i], " ")
    }
}

Map

package main

import "fmt"

func main() {
    world := make(map[string]string)
    world["China"] = "中国"
    world["America"] = "美国"
    //使用一个返回值,这个默认的返回值就是Map的键
    for country := range world {
        fmt.Println(world[country])
    }
    score := map[string]int{"one": 78, "two": 99}
    for k, v := range score {
        fmt.Println(k, "--", v)
    }
    fmt.Println(exist(score, "three")) //-1
    fmt.Println(exist(score, "one"))   //78
    delete(score, "one")
    fmt.Println(exist(score, "one")) //-1
}

func exist(m map[string]int, sc string) int {
    v, ok := m[sc]
    if ok {
        return v
    } else {
        return -1
    }
}

方法与函数

函数是指不属于任何结构体、类型的方法,也就是说,函数是没有接收者的;而方法是有接收者的,我们说的方法要么是属于一个结构体的,要么属于一个新定义的类型的

/*
 提供的常用库,有一些常用的方法,方便使用
*/
package lib

// 一个加法实现
// 返回a+b的值
func Add(a, b int) int {
    return a + b
}

函数名首字母小写,表示只能在该包内可见;首字母大写可供其他包调用。


两种类型的接收者:值接收者和指针接收者

在调用方法的时候,传递的接收者本质上都是副本,只不过一个是这个值副本,一是指向这个值指针的副本。指针具有指向原有值的特性,所以修改了指针指向的值,也就修改了原有的值。我们可以简单的理解为值接收者使用的是值的副本来调用方法,而指针接收者使用实际的值来调用方法

package main

import (
    "fmt"
    "strings"
)

type User struct {
    name string
    pwd  string
}

func (an *User) initPwd() (result bool, pwd string) {
    if strings.HasPrefix(an.name, "us") {
        an.pwd = "123456"
        result = true
    } else {
        result = false
    }
    pwd = an.pwd
    return
}

func (an User) login() bool {
    if an.pwd == "123456" {
        return true
    } else {
        return false
    }
}

func main() {
    user := User{name: "us_andy"}

    result, pwd := user.initPwd()
    if result {
        fmt.Printf("success! pwd = %s", pwd)
    } else {
        panic("fail pwd")
    }

    //ok := (&user).login()
    ok := user.login()
    if ok {
        fmt.Println("login success")
    } else {
        fmt.Println("login fail")
    }

}

函数作为参数

package main

import (
    "fmt"
)

func main() {
    callback(2, 1, Add)
}

func Add(a, b int) {
    fmt.Printf("The sum of %d and %d is: %d\n", a, b, a+b)
}

func callback(x int, y int, f func(int, int)) {
    f(x, y)
}

类型转换

package main

import "fmt"

type Filter func(it Base) bool

func ApplyFilter(list []Base, filters ...Filter) []Base {
    temp := make([]Base, 0, len(list))
    for _, v := range list {
        keep := true
        for _, f := range filters {
            if !f(v) {
                keep = false
                break
            }
        }
        if keep {
            temp = append(temp, v)
        }
    }
    return temp
}

type Base interface {
    driver() string
}

type Heart interface {
    boot()
}

type Diagram struct {
    id   int
    name string
}

func (d Diagram) driver() string {
    return "diagram driver"
}

func (d Diagram) boot() {
    s := d.driver()
    fmt.Println("boot..." + s)
}

type Canvas struct {
    id    int
    name  string
    shape string
}

func (c Canvas) driver() string {
    return "canvas driver"
}

func main() {
    var recorders = make([]Base, 3, 3)
    diagram := Diagram{1, "diagram1"}
    recorders[0] = diagram
    canvas := Canvas{id: 1, name: "canvas1", shape: "circle"}
    recorders[1] = canvas
    recorders = append(recorders, Canvas{2, "canvas2", "rectangle"})
    re := ApplyFilter(recorders, func(it Base) bool {
        //判断是否实现某接口,类型转换
        if sv, ok := it.(Heart); ok {
            sv.boot()
        }
        //类型判断
        switch it.(type) {
        case Canvas:
            ca := it.(Canvas)
            //做转换之后才可以访问具体类型的属性
            if ca.shape == "rectangle" {
                return true
            } else {
                return false
            }
        case Diagram:
            return false
        }
        return false
    })
    fmt.Println(re) //canvas
}

猜你喜欢

转载自blog.csdn.net/weixin_34161083/article/details/87225920
今日推荐