26

go语言入门经典

 4 years ago
source link: https://studygolang.com/articles/30568
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Go 谷歌新语言 不损失应用程序性能的情况下降低代码复杂性 具有部署简单 并发性好 语言设计良好 执行性能好的优势

对类C语言的重大改进 能够访问底层操作系统,还提供了强大的网络编程和并发编程支持。

常用于

  • 网络编程
  • 系统编程
  • 并发编程
  • 分布式编程

go语言是一门现代编程语言 可用来创建性能卓越的web服务器和系统程序。

go是编译型语言

go version
go version go1.15.1 darwin/amd64

go环境配置

mac@macdeMacBook-Pro ~ % mkdir $HOME/go
mac@macdeMacBook-Pro ~ % mkdir $HOME/go/bin
mac@macdeMacBook-Pro ~ % mkdir $HOME/go/pkg
mac@macdeMacBook-Pro ~ % mkdir $HOME/go/src
export GOPATH=$HOME/go

使用GitHub分享代码

mkdir -p $GOPATH/src/github.com/199305a

go hello world

package main
import (
    "fmt"
)
func main() {
    fmt.Printf("hello wprld")
}

运行helloworld

go run main.go

go的类型

数据类型是一种重要的编程计算结构

布尔类型

var b bool

数值

var i int = 3

浮点数

var f float32 = 0.111

字符串

var s string = "foo"

数组

var beatles [4]string

类型检查

reflect.TypeOf(s)

类型转换

strconv.FormatBool(b)

变量

var s string = "foo"

快捷声明变量

var s,t string = "foo","bar"
    var (
        x string = "x"
        y int = 4
    )

变量声明时未赋值使用 默认零值

简短声明变量

s := "hello world"

不能在函数外面使用简短变量声明

通常在函数外使用省略类型声明方式

在函数内使用简短变量声明

理解变量作用域

使用指针 &s

s,t  := "foo","bar"
     fmt.Println(&s,t)

指针传递 打印指针内容 *x

func showMemoryAddress(x *string)  {
    fmt.Println(x);
    fmt.Println(*x);
}

声明常量 const

const  greeting string  = "hello world"

使用函数

函数是接受输入并返回输出

func addUp(x int,y int) int {
    return  x + y
}

返回多个值

func getPrize() (int, string) {
    i := 2
    s := "goldfish"
    return i, s
}

定义不定参数函数 可使用3个点

使用具名返回值

func sayHi()(x,y string)  {
    x = "hello"
    y = "world"
    return 
}

使用递归函数

将函数作为值传递

func  anotherFunction(f func() string) string  {
    return  f()
}

func main() {
    fn := func() string {
        return "function called"
    }
    fmt.Println(anotherFunction(fn))
}

控制流程 if else elseif

使用if语句

func  test()  {
    b := false
    if b {
        fmt.Println("b is true")
    }
}

使用else语句 else if

使用比较运算符

== != >= <= > <

使用算术运算符

+ - * / %

使用逻辑运算符

&& || !

使用 switch 语句

func test1() {
    i := 2
    switch i {
    case 1:
        fmt.Println("One")
    case 2:
        fmt.Println("Two")
    case 3:
        fmt.Println("Three")
     default:   
    }
}

使用for循环 range

func test2() {
    i := 0
    for i < 10 {
        fmt.Println("i is", i)
        i++

    }
    for i := 0; i < 10; i++ {
        fmt.Println("i is", i)
    }
    numbers := []int{1, 2, 3, 4}
    for i, n := range numbers {
        fmt.Println("The index of the loop is", i)
        fmt.Println("The value from the array is", n)
    }
}

使用 defer语句 多条语句倒序执行

func test3()  {
    defer  fmt.Println("i am run after the func complete")
    fmt.Println("hello world")
}
hello world
i am run after the func complete

数组 切片和映射

使用数组 长度固定

var cheese [2]string

使用切片 更加灵活

var cheese = make([]string,2)

在切片添加元素 append

从切片中删除元素 删除索引2处的元素

append(cheese[:2],cheese[2+1:]...)

复制切片中的元素

copy(cheese,cheeses[1:])

使用映射

func test5()  {
    var players = make(map[string]int)
    players["cook"] = 32
    players["bairstow"] = 27
    players["stokes"] = 26
    fmt.Println(players["cook"])
}

从映射中删除元素

delete(players,"stokes")

结构体是什么

结构体是一系列具有指定数据类型的数据字段

type Movie struct {
    Name string
    Rating float32
}

func test6()  {
     m := Movie{
         Name:   "Citizen Kane",
         Rating: 10,
     }
     fmt.Println(m)
}

嵌套结构体

自定义结构体数据字段的默认值

比较结构体 如果结构体类型不同 将会出现编译错误

理解公有和私有值

私有值只能在其所属上下文中使用

要导出结构体及其字段 字段名称必须以大写字母开头

区分指针引用和值引用

结构体是值引用

变为指针引用

n := &m

创建方法和接口

使用方法 附加在实例上

func (m * Movie) summary() string  {
    
}
m.summary()

创建方法集

使用方法和指针

package main

import "fmt"

type Triangle struct {
    base float64
    height float64
}

func (t * Triangle) changeBase(f float64)  {
    t.base = f
    return
}

func main() {
  t := Triangle{base:3,height:1}
  t.changeBase(4)
  fmt.Println(t.base)
}

使用接口

type Robot interface {
    PowerOn() error
}

type  R2D2 struct {
    Broken bool
}

func (r * R2D2) PowerOn() error {
    if r.Broken {
        return  errors.New("R2D2 is broken")
    }else  {
        return nil
    }
}

使用字符串

字符串字面量

s := "I am an interpreted string Literal"

rune字面量

`

s := "I am an interpretedn string Literal"

`

拼接字符串 使用运算符+

s1 :="Oh sweet ignition" + "be my fuse"
intToString := strconv.Itoa(i1)

使用缓冲区拼接字符串

var buffer bytes.Buffer
    for i :=0;    i < 500;i++  {
        buffer.WriteString("z")
    }
    fmt.Println(buffer)

字符串 字节切片

处理字符串

将字符串转换为小写

fmt.Println(strings.ToLower("VERY BEAUTIFUL"))

在字符串中查找子串

fmt.Println(strings.Index("VERY surface","face"))

删除字符串首位的空格

fmt.Println(strings.TrimSpace("VERY BEAUTIFUL"))

处理错误

错误处理及Go语言的独特之处

file,err := ioutil.ReadFile("foo.txt")
    if err != nil{
         fmt.Println(err)
        return
    }
    fmt.Println("%s",file)

理解错误类型

创建错误

err := errors.New("Something went wrong")
    if err != nil {
         fmt.Println(err)
    }

从函数返回错误

func Half(numberToHalf int) (int, error) {
    if numberToHalf%2 != 0 {
        return -1, fmt.Errorf("Cannot half %v", numberToHalf)
    }
    return numberToHalf / 2, nil
}

错误和可用性

慎用 panic 会终止程序

使用Goroutine 并发

理解并发

并发和并行 并发 多个任务同时执行

并行 任务分成多个部分进行执行

并发就是同时处理很多事情 并行就是同时做很多事情

通过web浏览器来理解并发

阻塞和非阻塞代码

time.Sleep(time.Second * 2)

使用Goroutine处理并发操作

函数前添加go 来是函数异步执行

go    test6()

通道简介

使用通道

func slowFunc(c chan string)  {

    time.Sleep(time.Second * 2)
    c <- "slowFunc() finished"

}
func test1()  {
    c :=make(chan  string)
    go slowFunc(c)
    msg := <-c
    fmt.Println(msg)
}

使用缓冲通道 指定通道数量 最后close通道

func slowFunc(c chan string)  {

    time.Sleep(time.Second * 2)
    c <- "slowFunc() finished1"
    c <- "slowFunc() finished2"

}
func test1()  {
    c :=make(chan  string,2)
    go slowFunc(c)
    msg1 := <-c
    msg2 := <-c
    close(c)
    fmt.Println(msg1,msg2)
}

阻塞和流程控制

使用for阻塞流程

func slowFunc(c chan string)  {
  t := time.NewTicker(1 * time.Second)
    for  {
        c <- "ping"
        <-t.C
    }
}
func test2()  {
    message := make(chan string)
    go slowFunc(message)
    for {
        msg := <-message
        fmt.Println(msg)
    }
}

将通道用作函数参数

<- 位于chan左边 表示制度 位于右边 表示只写

使用select语句 当接收到一条数据时 将不再阻塞

func test3() {
    channel1 := make(chan string)
    channel2 := make(chan string)
    select {
    case msg1 := <-channel1:
        fmt.Println("received", msg1)
    case msg2 := <-channel2:
        fmt.Println("received", msg2)
    }
}

退出通道

case <- stop

func sender(c chan string)  {
    t := time.NewTicker(1 * time.Second)
    for {
        c <- "I a messgae"
        <-t.C
    }
}

func test1()  {
    messages := make(chan string)
    stop := make(chan  bool)
    go sender(messages)
    go func() {
        time.Sleep(time.Second * 2)
        fmt.Println("Time is up")
        stop <- true
    }()
    for  {
        select {
        case <-stop:
            return
        case msg := <-messages:
            fmt.Println(msg)

        }
    }
}

使用包实现代码重用

导入包

import (
    "fmt"
    "time"
)

使用第三方包

go get github.com/golang/example/stringutil

func test2()  {
    s := "ti ercesxsc"
    fmt.Println(stringutil.Reverse(s))
}

管理第三方依赖

go get u all

GO111MODULE=auto
go run hello.go

创建包

package temperature

func CtoF(c float64)float64 {
    return (c * (9 / 5)) + 32
}
func FtoC(c float64)float64 {
    return (c - 32) * (9 / 5)
}

Go语言命名约定

Go代码格式设置

使用gofmt

gofmt temperature.go

gofmt -w temperature.go

配置文本编辑器

有疑问加站长微信联系

iiUfA3j.png!mobile

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK