• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

go语言学习_incomplete

武飞扬头像
香蕉割草机
帮助1

前言

rust没咋整明白,再来了解下go语言基础知识,参考资料为菜鸟教程以及go程序设计语言。go语言与谷歌关系匪浅,且发明人之一还是c语言的发明人之一,可以说是很神奇了。

构建系统

go和cargo的编译命令挺像,也有build和run

编码风格

关于函数大括号,go似乎更严格,虽然rust有标准风格,但括号不在同一行也可以编译通过,而go会直接报错:

~/project/hello_go$ go build hello.go
# command-line-arguments
./hello.go:6:1: syntax error: unexpected semicolon or newline before {

go也有gofmt可以格式化代码。
与python一样,一行代表一个语句结束,如果想在一行写多个语句,可以使用;分隔。
注释与c相同,使用//和/**/。
go语言中标识符的开头字母的大小写决定了这个符号是否是外部符号,大写可以被其他人所用,否则只能在包内部可见并可用。
与python一样,go支持字符串通过 连接。

数据类型

布尔

数字

和rust类似,以占用空间大小命名类型,包括各种有符号无符号的整型,浮点型,另外还有byte,rune,uint,int与uintptr等类型。

字符串

派生类型

指针

go中的指针与c中的也很像

数组

形式如下:

var variable_name [SIZE] variable_type

go中的数组与c中的很像,只是语法不同。

结构体

同上,和c很像

Channel类型

函数

切片

声明形式:

//声明一个未指定大小的数组来定义切片:切片不需要说明长度。
var identifier []type

//或使用 make() 函数来创建切片:
var slice1 []type = make([]type, len)

//也可以简写为

slice1 := make([]type, len)
//也可以指定容量,其中 capacity 为可选参数。
make([]T, length, capacity)

需要注意的是不要和长度不确定的数组的定义混了,长度不定数组定义实例:

var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

切片有点像可变长数组

接口类型

形式:

/* 定义接口 */
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

/* 定义结构体 */
type struct_name struct {
   /* variables */
}

/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
   /* 方法实现 */
}
...
func (struct_name_variable struct_name) method_namen() [return_type] {
   /* 方法实现*/
}
学新通

实例:

package main

import (
    "fmt"
)

type Phone interface {
    call()
}

type NokiaPhone struct {
}

func (nokiaPhone NokiaPhone) call() {
    fmt.Println("I am Nokia, I can call you!")
}

type IPhone struct {
}

func (iPhone IPhone) call() {
    fmt.Println("I am iPhone, I can call you!")
}

func main() {
    var phone Phone

    phone = new(NokiaPhone)
    phone.call()

    phone = new(IPhone)
    phone.call()

}
学新通

Map类型

map的定义同样使用make:

/* 使用 make 函数 */
map_variable := make(map[KeyType]ValueType, initialCapacity)

类型转换

形式:

type_name(expression)

实例:

var a int = 10
var b float64 = float64(a)

变量

go是强类型语言。

变量声明

第一种,指定变量类型,如果没有初始化,则变量默认为零值。
形式如下:

var v_name v_type
v_name = value

第二种,根据值自行判定变量类型。
形式如下:

var v_name = value

第三种,如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误,格式:

v_name := value

intVal := 1 相等于:

var intVal int 
intVal =1 

这也就是说go中不能二次声明。
多变量声明
形式如下:

//类型相同多个变量, 非全局变量
var vname1, vname2, vname3 type
vname1, vname2, vname3 = v1, v2, v3

var vname1, vname2, vname3 = v1, v2, v3 // 和 python 很像,不需要显示声明类型,自动推断

vname1, vname2, vname3 := v1, v2, v3 // 出现在 := 左侧的变量不应该是已经被声明过的,否则会导致编译错误

a, b, c := 5, 7, "abc"

// 这种因式分解关键字的写法一般用于声明全局变量
var (
    vname1 v_type1
    vname2 v_type2
)

交换变量值

a, b = b, a

作用域

基本与c相同,局部变量,全局变量等

常量

定义实例如下:

const b string = "abc"//显式类型定义
const b = "abc"//隐式类型定义

用做枚举:

const (
    Unknown = 0
    Female = 1
    Male = 2
)

iota,特殊常量,可以认为是一个可以被编译器修改的常量。
iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。
iota 可以被用作枚举值:

const (
    a = iota
    b = iota
    c = iota
)

简写如下:

const (
    a = iota
    b
    c
)

不要把这个和itoa混了。

Range

与python中的range可以产生序列不同,go中的range用于迭代遍历成员。

运算符

运算符和c基本一致

控制流

分支

if
else if
else
switch
select

循环

for

函数

定义形式:

func function_name( [parameter list] ) [return_types] {
   函数体
}

例子:

/* 函数返回两个数的最大值 */
func max(num1, num2 int) int {
   /* 声明局部变量 */
   var result int

   if (num1 > num2) {
      result = num1
   } else {
      result = num2
   }
   return result 
}

函数可以返回多个值

值传递和引用传递

和c类似,传引用是通过指针实现的。

函数作为实参

package main

import (
   "fmt"
   "math"
)

func main(){
   /* 声明函数变量 */
   getSquareRoot := func(x float64) float64 {
      return math.Sqrt(x)
   }

   /* 使用函数 */
   fmt.Println(getSquareRoot(9))

}
学新通

闭包

package main

import "fmt"

func getSequence() func() int {
   i:=0
   return func() int {
      i =1
     return i  
   }
}

func main(){
   /* nextNumber 为一个函数,函数 i 为 0 */
   nextNumber := getSequence()  

   /* 调用 nextNumber 函数,i 变量自增 1 并返回 */
   fmt.Println(nextNumber())
   fmt.Println(nextNumber())
   fmt.Println(nextNumber())
   
   /* 创建新的函数 nextNumber1,并查看结果 */
   nextNumber1 := getSequence()  
   fmt.Println(nextNumber1())
   fmt.Println(nextNumber1())
}
学新通

方法

形式如下:

func (variable_name variable_data_type) function_name() [return_type]{
   /* 函数体*/
}

实例:

package main

import (
   "fmt"  
)

/* 定义结构体 */
type Circle struct {
  radius float64
}

func main() {
  var c1 Circle
  c1.radius = 10.00
  fmt.Println("圆的面积 = ", c1.getArea())
}

//该 method 属于 Circle 类型对象中的方法
func (c Circle) getArea() float64 {
  //c.radius 即为 Circle 类型对象中的属性
  return 3.14 * c.radius * c.radius
}
学新通

错误处理

实例:

package main

import (
    "fmt"
)

// 定义一个 DivideError 结构
type DivideError struct {
    dividee int
    divider int
}

// 实现 `error` 接口
func (de *DivideError) Error() string {
    strFormat := `
    Cannot proceed, the divider is zero.
    dividee: %d
    divider: 0
`
    return fmt.Sprintf(strFormat, de.dividee)
}

// 定义 `int` 类型除法运算的函数
func Divide(varDividee int, varDivider int) (result int, errorMsg string) {
    if varDivider == 0 {
            dData := DivideError{
                    dividee: varDividee,
                    divider: varDivider,
            }
            errorMsg = dData.Error()
            return
    } else {
            return varDividee / varDivider, ""
    }

}

func main() {

    // 正常情况
    if result, errorMsg := Divide(100, 10); errorMsg == "" {
            fmt.Println("100/10 = ", result)
    }
    // 当除数为零的时候会返回错误信息
    if _, errorMsg := Divide(100, 0); errorMsg != "" {
            fmt.Println("errorMsg is: ", errorMsg)
    }

}
学新通

并发

协程

形式:

go 函数名( 参数列表 )

实例:

package main

import (
        "fmt"
        "time"
)

func say(s string) {
        for i := 0; i < 5; i   {
                time.Sleep(100 * time.Millisecond)
                fmt.Println(s)
        }
}

func main() {
        go say("world")
        say("hello")
}
学新通

通道

创建通道形式如下:

ch := make(chan int)

实例:

package main

import "fmt"

func sum(s []int, c chan int) {
        sum := 0
        for _, v := range s {
                sum  = v
        }
        c <- sum // 把 sum 发送到通道 c
}

func main() {
        s := []int{7, 2, 8, -9, 4, 0}

        c := make(chan int)
        go sum(s[:len(s)/2], c)
        go sum(s[len(s)/2:], c)
        x, y := <-c, <-c // 从通道 c 中接收

        fmt.Println(x, y, x y)
}
学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgfbfhh
系列文章
更多 icon
同类精品
更多 icon
继续加载