写给大忙人看的Go语言(一)

栏目: Go · 发布时间: 6年前

内容简介:写给大忙人看的Golang教程(一)阅读本文之前,我认为你已经掌握其他语言基础并写出一个简单的项目。

Tips

写给大忙人看的Golang教程(一)

阅读本文之前,我认为你已经掌握其他语言基础并写出一个简单的项目。

(1)Golang编程注意事项

.go
main()

(2)Golang中的常用转义字符

\t
\n
\\
\"
\r

(3)注释方式

// 注释内容
/* 注释内容 */

(4)Golang的代码规范

  • 尽量使用行注释注释整个方法或语句
  • 使用Tab缩进
  • 使用 gofmt -w 格式化代码
  • 运算符两侧加空格
  • Golang的代码风格:

    // HelloWorld.go
    
    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("Hello World")
    }
  • 一行代码最好不要超过80个字符

(5)官方编程指南

(6)变量

  • 使用 var 关键字定义变量: var 变量名称 数据类型
  • 使用类型推导: var 变量名称 = 值
  • 省略 var 关键字: 变量名称 := 值 , 变量名称不应该是已经定义过的
  • 变量名称 := 值 等同于 var 变量名称 数据类型 = 值
  • 多变量声明: var 变量名称, 变量名称... 数据类型
  • 多变量赋值: var 变量名称, 变量名称, ... = 值, 值, ...
  • 省略 var 关键字多变量声明和赋值: 变量名称, 变量名称, ... := 值, 值, ...
  • 声明全局变量:
    var (
        变量名称 = 值
        ...
    )

(7)Golang支持的数据类型

写给大忙人看的 <a href='https://www.codercto.com/topics/6127.html'>Go</a> 语言(一)

  • 使用 unsafe.Sizeof() 查看变量占用的空间

    package main
    
    import (
    "fmt"
    "unsafe"
    )
    
    func main() {
    var x int = 10
    fmt.Println("The x size: ", unsafe.Sizeof(x))
    // The x size:  8
    }
  • float32 表示单精度, float64 表示双精度

  • 字符常量使用单引号

  • Go中的字符编码使用 UTF-8 类型

  • bool 类型只能取 truefalse

  • 在Go中字符串是不可变的

  • Go支持使用反引号输出原生字符串

  • 字符串拼接使用加号时最后一个加号需要保留在行尾

(8)基本数据类型转换

  • 数值类型互相转换: 目标数据类型(变量)
  • 数值与字符串互转:
    • 数字转字符串:使用 fmt.Sprintf() 字符串格式化函数。
    • 数字转字符串:使用 strconv.FormatBool()strconv.FormatInt()strconv.FormatUint()strconv.FormatFloat() 格式化函数。
    • 字符串转数字:使用 strconv.ParseBool()strconv.ParseInt()strconv.ParseUint()strconv.ParseFloat() 格式化函数。

(9)指针数据类型

package main

import "fmt"

func main() {

    var i = 10
    var ptr *int = &i

    fmt.Println("变量i的内存地址是: ", ptr)
    // 变量i的内存地址是:  0xc00004a080
    fmt.Println("变量i的存储内容是: ", *ptr)
    // 变量i的存储内容是:  10
}

(10) 值类型与引用类型

写给大忙人看的Go语言(一)

写给大忙人看的Go语言(一)

  • 值类型通常存放到栈区。
  • 引用类型通常存放在堆区,栈中有堆中的引用。

(11)Golang中的标识符

_

(12)运算符

  • Golang中只有 x++x-- ,没有 ++x--x
  • 自增自减运算值独立的语句,不允许类似的: x := a++

(13)控制台输入输出

fmt.Sacnf()
fmt.Sacnln()

(14) 原码、反码、补码

  • 计算机中0表示正数,1表示负数
  • 计算机中都是用补码进行运算的,因为CPU只会加法运算
  • 正数的原、反、补都是相同的
  • 负数的反码是原码符号位不变其他位取反
  • 负数的补码是反码加1
  • 0的原、反、补相同

(15)流程控制

(15.1)顺序控制

(15.2) 分支控制

  • if 语句:

    if x>12 { 
    }
    // Golang支持直接在condition中定义变量
    if x:=12; x>12 {
    }
  • if-else 语句:

    if x:=12; x>20 {
    }else {
    }
  • if-else if-else 语句:

    if x:=12; x>100 {
    }else if x>50 {
    }else if x>10 {
    }else {
    }
  • switch-case-default 语句:

    // 每个分支不需要break语句
    // switch也支持在condition中直接定义变量
    // case支持多个表达式
    // 取消break使用fallthrough语句————switch穿透
    switch y:=10;y {
    case 5:
        // something
    case 10:
        // something
        fallthrough
    case 20, 25, 30:
        // something
    default:
        // something
    }

(15.3)循环控制

  • for 循环

    for i:=1;i<10;i++ {
    }
    // Golang也提供了for-each或for-range类似的循环
    str := "Hello Golang."
    for index, value:=range str {
      // index表示索引
      // value表示值
    }
  • while 循环

    for {
      if condition {
          break
      }
      // something
    }
  • do-while 循环

    for {
      // something
      if condition {
          break
      }
    }

(16) 随机数

// 设置随机数的种子为当前的系统时间
rand.Seed(time.Now().Unix())
// 生成0-99范围的随机数
randomNumber := rand.Intn(100)

(17)break、continue、goto、return语句

  • break 语句在多层嵌套中可以通过标签指明要终止到哪一层语句块:
label:
for {
    break label
}
  • continue 语句在多层嵌套中可以通过标签指明要跳出到到哪一层语句块:
label:
for {
    continue label
}
  • goto 语句可以无条件跳转,容易造成逻辑混乱,一般不主张使用 goto 语句:

    label:
    for {
    goto label
    }
  • return 语句用户退出函数
    return
    // 或
    return some

(18)函数

  • 函数基本语法:

    func functionName (paramsList) (returnList) {}
  • Golang不支持函数重载

  • Golang函数本身也是一种数据类型,可以赋值给变量,那么该变量也是函数类型

  • Golang函数可以作为实参传入另一个函数

  • Golang支持自定义数据类型,使用: type 自定义数据类型名 数据类型

    type myfunc func(int)(int, int)
  • 支持使用 _ 忽略返回值

  • 支持可变参数

    package main
    
    import "fmt"
    
    func main() {
    ret := sum(1, 2, 3)
    fmt.Println(ret) //6
    }
    // 可变参数
    func sum(args...int) int {
    
    sum := 0
    
    for i:=0; i<len(args); i++ {
        sum += args[i]
    }
    
    return sum
    }

(19)包

​ 包的本质就是一个目录,Go的每一个文件都必须属于一个包。

  • 打包:

    package packageName
  • 导入包:

    import "packageName"
    // 导入多个包
    import (
    "packageName"
      ...
    )
    // 导入包时自动从GOPATH下面的src下面引入
  • 包支持别名

    package main
    
    import f "fmt"
    
    func main() {
    f.Println()
    }

(20) init 函数

  • 在Go中每一个源文件都可以有一个 init 函数,它优先于 main 函数执行,被Go框架调用。
func init() {}
  • 先执行引入的包中的 init 函数再执行 main 包中的 init 函数
// util.HelloWorld.go
package utils

import "fmt"

func init() {
    fmt.Println("Util.HelloWorld() init")
}

func HelloWorld()(){
    fmt.Println("Hello World")
}

// main.test.go
package main

import (
    "StudyGo/utils"
    "fmt"
)

func init() {
    fmt.Println("Main.main() init")
}

func main() {
    utils.HelloWorld()
}

// Util.HelloWorld() init
// Main.main() init
// Hello World

(21)匿名函数

  • 直接调用

    func (paramsList)(returnList){
        // something
    }()
  • 赋值给一个变量

    x := func (paramsList)(returnList){
        // something
    }
    y := x(paramsList)

(22)闭包

  • 闭包就是函数与其相关的引用环境构成的实体

    package main
    
    import (
        "fmt"
        "strings"
    )
    
    func main() {
    
        fileName := "file"
        fileSuffix := ".mp3"
    
        ms := makeSuffix(fileSuffix)
        ret := ms(fileName)
    
        fmt.Println(ret)
    
    }
    
    func makeSuffix(suffix string) func(string) string {
        return func (s string) string {
            if strings.HasSuffix(s, suffix) {
                return s
            }else {
                return s + suffix
            }
        }
    }

(23)defer 关键字

  • defer是Go语言中的延时机制,用于处理关闭文件句柄等资源释放操作

    package main
    
    import "fmt"
    
    func main() {
    SayHello()
    }
    
    func SayHello() {
    defer fmt.Println("Bye.")
    fmt.Println("Hi.")
    }
    
    // Hi.
    // Bye.
  • 使用defer修饰的语句会压入栈中,其相关的值也会被压入栈中

(24) 字符串函数

len()
strconv.Atoi(s string) (i int, err error)
strconv.Itoa(i int) string
strconv.FormatInt(i int64, base int) string
strings.Contains(s string, sub string) bool
strings.Count(s string, sub string) int
strings.EqualFold(s_0 string, s_1 string) bool
strings.Index(s string, sub string) int
strings.LastIndex(s string, sub string)
string.Replace(s string, oldSub string, newSub string, n int) string
string.ToLower(s string)
string.ToUpper(s string)
string.Split(s string, sep string) array
string.TrimSpace(s string) string
string.Trim(s string, sub string) string
string.TrimLeft(s string, sub string) string
string.TrimRight(s string, sub string) string
string.HasPrefix(s string, sub string) bool
string.HasSuffix(s string, sub string) bool

(25)时间日期函数

  • time.Time :表示时间类型
  • time.Now() struct :获取当前本地时间
  • time.Now().Year() :返回年
  • time.Now().Month() :返回月,使用 int(time.Now().Month()) 取得数字
  • time.Now().Day() :返回日
  • time.Now().Hour() :返回时
  • time.Now().Minute() :返回分
  • time.Now().Second() :返回秒
  • time.Now().Format(s string) :格式化时间数据, 2006-01-02 15:04:05 表示格式化的格式字符串其中的值不能改变
  • time.Sleep(d Duration) :休眠函数
    time.Hour
    time.Minute
    time.Second
    time.Millisecond
    time.Microsecond
    time.Nanosecon
    
  • time.Now().Unix() int64 :返回Unix秒时间戳
  • time.Now().UnixNano() int64 :返回Unix纳秒时间戳

(26)内置函数

len()
new()
make()

(27)错误处理

  • 在Go中捕获异常的机制是使用 defer 关键字修饰匿名函数,导致匿名函数最后执行,在匿名函数中调用 recover() 函数,通过返回值是否为 nill 来判断是否发生异常信息。

    package main
    
    import "fmt"
    
    func main() {
    
        ret := ComputeNumber(1, 0)
        fmt.Println(ret)
    }
    
    func ComputeNumber(n_0 int, n_1 int) int {
    
        defer func() {
            if e := recover(); e != nil{
                fmt.Println(e)
            }
    
        }()
    
        result := n_0 / n_1
    
        return result
    }
  • 自定义错误

    使用 errors.New(Type) *Type 创建一个 error 类型, panic() 接收一个空接口类型,输出错误信息并结束运行。

    package main
    
    import "errors"
    
    func main() {
    
    err := readConfigureFile("config.json")
    
    if err !=nil {
        panic(err) // panic: Read config.ini error.
    }
    
    }
    
    func readConfigureFile(path string)(err error) {
    
    if path != "config.ini" {
        return errors.New("Read config.ini error.")
    } else {
        return nil
    }
    }

    (28)数组

    ​ 在Go中数据是值类型,使用以下方式创建数组。

    var 数组名称 [元素个数]数据类型 = [元素个数]数据类型{元素}
    var 数组名称 = [元素个数]数据类型{元素}
    var 数组名称 = [...]数据类型{元素个数}
    var 数组名称 = [...]数据类型{索引:值}
    for-each/for-range
    

    (29)slice 切片

    数组的长度是固定的,切片 的长度不是固定的。

    • var 切片名称 []数据类型

    • 切片名称[索引:索引]

    • 切片的结构: [起始数据元素指针, 长度, 容量]

    • 通过make创建切片: var 切片名称 []数据类型 = make([]数据类型, 长度, 容量)

    • 切片支持普通遍历和 for-range 方式遍历

    • 使用 append() 函数追加元素到切片末尾,容量不够时自动扩容

    • 使用 copy() 函数拷贝数组

    • string 类型底层是个 byte 数组,也可以进行切片处理。 string 是不可变的,如果要修改字符串,需要先将字符串转换为切片修改完成后再转换成为字符串。
    str := "Hello World."
    arr := []byte(str)
    arr[11] = '!'
    str = string(arr)
    fmt.Println(str)

    (28)Map映射

    • Map是一种键值对数据结构,声明方式如下:

    var Map名称 map[KeyType]ValueType

    • 使用 make(map[KeyType]ValueType) 分配空间

    • delete(m map[Type]Type, key Type) :通过Key删除元素,如果元素不存在也不会报错

    • 清空Map一种是遍历删除,一种是 make 重新分配空间,使得原来的Map成为垃圾让GC回收

    • 查找使用 value, ok = mapName[Key] ,如果 oktrue ,表示元素存在

    • Map支持 for-range 遍历
    for key, value := range mapName{
    }
    • Map支持切片

(28)OOP

  • Go中的OOP是通过 struct 来实现的

    type 类名 struct {
      属性名 数据类型
      ...
    }
  • 创建结构体变量

    var 变量名称 结构体类型
    var 变量名称 结构体类型 = 结构体类型{}
    变量名称 := 结构体类型{}
    
    // 下面两种写法等价:
    var 变量名称 *结构体名称 = new(结构体名称)
    var 变量名称 *结构体名称 = &结构体名称
    
    // 在操作属性、方法的时候Go进行了优化,下面两种写法是等价的:
    (*变量名称).属性 = 值
    变量名称.属性 = 值
  • 每一个字段可以加上一个tag,该tag可以通过反射机制获取,常见的场景就是序列化与反序列化

    属性名称 数据类型 `json:Tag名称`
  • Go中的类没有构造函数,通常通过工厂模式来实现

    package model
    
    // 如果Name和Age改为name和age,需要为person绑定Getter和Setter方法
    type person struct {
    Name string `json:"name"`
    Age int `json:"age"`
    }
    
    func NewPerson(n string, a int)(*person){
    return &person{
        Name : n,
        Age : a,
    }
    }
    package main
    
    import "fmt"
    import "StudyGo/model"
    
    func main() {
    var tom = model.NewPerson("Tom", 20)
    fmt.Println((*tom).Name)
    fmt.Println((*tom).Age)
    }
  • 在Go中在一个结构体中嵌套另一个匿名结构体就认为实现了继承

    type Ani struct {
      name string
      age int
    }
    
    type Cat struct {
      Ani
      say string
    }
    结构体变量.数据类型 = 值
    
  • 接口

    type 接口名称 interface {
      方法名称(参数列表)(返回值列表)
    }
    • 接口不允许包含任何变量
    • Go中的接口不需要显式实现,只要一个变量含有接口的所有方法,那么就实现了这个接口
  • 类型断言

    • 当一个类型转换为了接口类型在转换为该类型时需要使用类型断言判断是否可以转换为该类型
    var number float32
    var x interface{}
    x = t
    t = x.(float32) // 判断一下是否可以转换成为float32类型

(29)方法

func (recv type) funcName (paramsList)(returnList) {
    // something
}
  • recv 表示这个方法与 type 类进行绑定,方法内通过 recv 操作 type 类中的字段
  • type 是个结构体类型
  • recv 是个结构体类型变量

通常为了执行效率一般不会直接传入结构体类型作为接收器,而是结构体类型指针:

func (dog *Dog) function()(){ // 绑定的是地址,操作时也要使用地址
    // something
}
// 调用时
var d Dog
(&d).function()

但是编译器做出了相关的优化:

var d Dog
d.function()

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

最优化导论

最优化导论

桑达拉姆 / 人民邮电出版社 / 2008-4 / 59.00元

最优化导论(英文版),ISBN:9787115176073,作者:(美国)(Sundaram、R、K)桑达拉姆一起来看看 《最优化导论》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具