go语言入门经典

忘却° · · 532 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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的类型

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

配置文本编辑器


有疑问加站长微信联系(非本文作者)

本文来自:Segmentfault

感谢作者:忘却°

查看原文:go语言入门经典

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

532 次点击  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传