博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go基础1
阅读量:4647 次
发布时间:2019-06-09

本文共 11484 字,大约阅读时间需要 38 分钟。

基础语法:

// ---------------------------------------变量声明

var [名称] [类型]

var name string

1)声明的变量一定要使用

2)声明同时初始化,可以不写后面类型:var sum = 17

多变量声明同其他语言var a,b int

 

// 自动推导类型

[名称] := [值]

name := "Bill"

1)注意只能在函数局部使用

2)只能使用一次,用于初始化,第一次出现使用

 

//多重初始化

a, b, c := 10, "abc", 1.0

 

//交换两个变量的值

A,b = b,a

 

//_匿名变量,丢弃数据不处理,一般是配合函数返回值使用

tmp,_ = i,j   //tmp=10,go函数支持返回多值

 

//不同类型变量的声明

var(

   a int = 1

   b string = “abc”

)

// ---------------------------------------常量

const [名称] [类型] = 值

const  a int = 3

const  b  = “abc”

1、 不能使用自动推导

2、 类型是可选选项

3、 同时声明多个:const a, b, c = 1, false, "str" //多重赋值

 

常量还可以用作枚举(声明多个常量):

const (

    Unknown = 0

    Female = 1

    Male = 2

)

 

 

// ---------------------------------------iota枚举

    const (

        x = iota // x == 0

        y = iota // y == 1

        z = iota // z == 2

        w  // 这里隐式地说w = iota,因此w == 3。其实上面y和z可同样不用"= iota"

    )

 

    const v = iota // 每遇到一个const关键字,iota就会重置,此时v == 0

 

    const (

        h, i, j = iota, iota, iota //h=0,i=0,j=0 iota在同一行值相同

    )

 

    const (

        a       = iota //a=0

        b       = "B"

        c       = iota             //c=2

        d, e, f = iota, iota, iota //d=3,e=3,f=3

        g       = iota             //g = 4

    )

   

    const (

        x1 = iota * 10 // x1 == 0

        y1 = iota * 10 // y1 == 10

        z1 = iota * 10 // z1 == 20

    )

1、 iota每隔一行,自动累计加1

2、 iota给常量赋值使用

3、 iota遇到const,重置为0

 

// ---------------------------------------注释

// 单行注释,CsCode快捷键Ctrl+/

/*

 Author by 多行注释

 我是多行注释

 */

 

// --------------------------------------- 类型转换

分兼容的直接转换,和不兼容的利用类库转换

不兼容的一般会类似这样提示

cannot convert  expression (type type_name) to type desctype_name

1、 兼容的可以直接转

type_name(expression)

mean = float32(sum) / float32(count)

var ch byte

ch = ‘a’

var t int

t = int(ch)//类型转换

2、 不兼容的可以利用函数strconv里面的方法进行转,一般会返回两个值,转换结果和报错信息

boolvalue, err := strconv.ParseBool("1")//int类型 转成 bool

i, err := strconv.Atoi(“123”) //string 类型 转成 int

 

 

// --------------------------------------- 变量输入

Var a int

fmt.Scan(&a)//输入值赋给a

 

 

// --------------------------------------- 类型别名type(把类型弄个自己的名字来用)

在结构体和方法里面会用到

Type 别名 类型

type bigint int64 //int64类型改名为bigint
var x bigint = 100//等价于var x int64 = 100
 
type (
      myint int    //int改名为myint
      mystr string //string改名为mystr
)

 

// ---------------------------------------  运算符

大同小异,这里列一些和C#不同的

1、++和—只有后自增和后自减

2、位运算符多了<<和>>

3、赋值运算符<<=、>>=

4、返回变量存储地址:&

5、指针变量:*

/*  & 和 * 运算符实例 */

var a int = 4

   var ptr *int

   ptr = &a    /* 'ptr' 包含了 'a' 变量的地址,*ptr就是a的值 */

   fmt.Printf("a 的值为  %d\n", a);

   fmt.Printf("*ptr 为 %d\n", *ptr);

a 的值为  4

*ptr 为 4

 

一元运算符拥有最高的优先级,二元运算符的运算方向均是从左至右。

下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:

优先级

运算符

7

^      !  

6

*       /    %    <<    >>    &      &^

5

+      -     |      ^

4

==   !=   <    <=    >=    >

3

<-

2

&&

1

||

 

 

// ---------------------------------------  if语句

If

if a < 20 {

       fmt.Printf("a 小于 20\n" )

   }

//支持一个初始化表达式, 初始化字句和条件表达式直接需要用分号分隔
    if b := 3; b == 3 {
        fmt.Println("b==3")
    }

    

If else

if a < 20 {//{不能跨行

       fmt.Printf("a 小于 20\n" );

   } else if {//{不能跨行

fmt.Printf("a 不小于 20\n" );

   }else {//{不能跨行

fmt.Printf("a 不小于 20\n" );

   }

 

if嵌套

if 布尔表达式 1 {

   /* 在布尔表达式 1 为 true 时执行 */

   if 布尔表达式 2 {

      /* 在布尔表达式 2 为 true 时执行 */

   }

}

 

 

 

Switch:和C#比,没括号(go里面,加括号,加分号,保存后,VsCode会自动去掉)

switch var1 {

    case val1:

        ...

case val2:

       ...

    default:

        ...

}

 

Type Switch

switch x.(type){

    case type:

       statement(s);     

    case type:

       statement(s);

    /* 你可以定义任意个数的case */

    default: /* 可选 */

       statement(s);

}

1. 支持多条件匹配

switch{

    case 1,2,3,4:

    default:

}

2. 不同的 case 之间不使用 break 分隔,默认只会执行一个 case。

3. 如果想要执行多个 case,需要使用 fallthrough 关键字(一般结尾加,没遇到break会继续执行下一个case分支),也可用 break 终止。

4、支持初始化语句

switch num := 1;num{

   case 1:

   default:

}

4、 switch可以没有条件,case放条件

score := 85

Switch{

Case score > 90:

fmt.mrintlc(“优秀”)

}

 

// ---------------------------------------  循环 for

有三种形式

1、for init; condition; post { }
2、for condition { }  //和while类似
3、for { } //相当于while(true),里面要加break跳出的
  • init: 一般为赋值表达式,给控制变量赋初值;
  • condition: 关系表达式或逻辑表达式,循环控制条件;
  • post: 一般为赋值表达式,给控制变量增量或减量。
    •     /* for 循环 */
    •     for a := 0; a < 10; a++ {
    •         fmt.Printf("a 的值为: %d\n", a)
    •     }

 

    for a < b {

        a++

        fmt.Printf("a 的值为: %d\n", a)

     }

 

 

 

// ---------------------------------------  迭代器range相当于C#foreach

关键字 range 会返回两个值(可以选择定义一个变量只接受一个值),第一个返回值是元素的数组下标,第二个返回值是元素的值:

    s := "abc"
    for i := range s { //支持 string/array/slice/map。
        fmt.Printf("%c\n", s[i])//只接受下标i
    }
 
    for _, c := range s { // 忽略 index
        fmt.Printf("%c\n", c)
    }
 
    for i, c := range s {
        fmt.Printf("%d, %c\n", i, c)
    }

 

 

 

// ---------------------------------------  goto

用goto跳转到必须在当前函数内定义的标签:

func main() {
    for i := 0; i < 5; i++ {
        for {
            fmt.Println(i)
            goto LABEL //跳转到标签LABEL,从标签处,执行代码
        }
    }
 
    fmt.Println("this is test")
 
LABEL:
    fmt.Println("it is over")
}

 

 

// --------------------------------------- 函数

func function_name( [parameter list] ) [return_types] {

   函数体

}

  • func:函数由 func 开始声明
  • function_name:函数名称,函数名和参数列表一起构成了函数签名。
  • parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
  • return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下 return_types 不是必须的。
  • 函数体:函数定义的代码集合。
  • 函数名首字母小写即为private,大写即为public
    • /* 函数返回两个数的和 */
    • func max(num1, num2 int) int {
    •    /* 声明局部变量 */
    •    var result int
    •    Result = num1 + num2
    •    return result
    • }
 

多个返回值

  • /* 函数返回两个数的和 */
  • func swap(num1 string, num2 int) (string,int) {
  •    return num1,num2
  • }

 

不定参数类型

不定参数是指函数传入的参数个数为不定数量。为了做到这点,首先需要将函数定义为接受不定参数类型:

//形如...type格式的类型只能作为函数的参数类型存在,并且必须是最后一个参数
func Test(args ...int) {
    for _, n := range args { //遍历参数列表
        fmt.Println(n)
    }
}
 
func main() {
    //函数调用,可传0到多个参数
    Test()
    Test(1)
    Test(1, 2, 3, 4)
}

 

2) 不定参数的传递

func MyFunc01(args ...int) {
    fmt.Println("MyFunc01")//len(args)
    for _, n := range args { //遍历参数列表
        fmt.Println(n)
    }
}
 
func MyFunc02(args ...int) {
    fmt.Println("MyFunc02")
    for _, n := range args { //遍历参数列表
        fmt.Println(n)
    }
}
 
func Test(args ...int) {
    MyFunc01(args...)     //按原样传递, Test()的参数原封不动传递给MyFunc01
    MyFunc02(args[1:]...) //Test()参数列表中,第1个参数及以后的参数传递给MyFunc02
}
 
func main() {
    Test(1, 2, 3) //函数调用
}

 

返回写法比较多样

单个返回值

func Test01() int { //方式1
    return 250
}
 
//官方建议:最好命名返回值,因为不命名返回值,虽然使得代码更加简洁了,但是会造成生成的文档可读性差
func Test02() (value int) { //方式2, 给返回值命名
    value = 250
    return value
}
 
func Test03() (value int) { //方式3, 给返回值命名
    value = 250
    return
}
 

多个返回值

func Test01() (int, string) { //方式1
    return 250, "sb"
}
 
func Test02() (a int, str string) { //方式2, 给返回值命名
    a = 250
    str = "sb"
    return

}

 

// --------------------------------------- 函数类型(有点像C#的委托)

在Go语言中,函数也是一种数据类型,我们可以通过type来定义它,它的类型就是所有拥有相同的参数,相同的返回值的一种类型。

 

type FuncType func(int, int) int //声明一个函数类型, func后面没有函数名
 
//函数中有一个参数类型为函数类型:f FuncType
func Calc(a, b int, f FuncType) (result int) {//Calc是执行的
    result = f(a, b) //通过调用f()实现任务
    return
}
 
//实际调用的函数实现
func Add(a, b int) int {
    return a + b
}
 
//实际调用的函数实现
func Minus(a, b int) int {
    return a - b
}
 
func main() {
    //函数调用,第三个参数为函数名字,此函数的参数,返回值必须和FuncType类型一致
    result := Calc(1, 1, Add)
    fmt.Println(result) //2
 
    var f FuncType = Minus
    fmt.Println("result = ", f(10, 2)) //result =  8
}

 

回调函数

就是利用函数类型实现

实际调用的函数是函数类型的实现

调用那个实现函数类型的是执行的主体

// --------------------------------------- 匿名函数与闭包

所谓闭包就是一个函数“捕获”了和它在同一作用域的其它常量和变量。这就意味着当闭包被调用的时候,不管在程序什么地方调用,闭包能够使用这些常量或者变量。它不关心这些捕获了的变量和常量是否已经超出了作用域,所以只有闭包还在使用它,这些变量就还会存在。

闭包需要匿名函数来实现(都是匿名函数)

在Go语言里,所有的匿名函数(Go语言规范中称之为函数字面量)都是闭包。匿名函数是指不需要定义函数名的一种函数实现方式。

func main() {
    i := 0
    str := "mike"
 
    //方式1,先定义,再赋函数
    f1 := func() { //匿名函数,无参无返回值
        //引用到函数外的变量
        fmt.Printf("方式1:i = %d, str = %s\n", i, str)
    }
 
    f1() //函数调用
 
    //方式1的另一种方式
    type FuncType func() //声明函数类型, 无参无返回值
    var f2 FuncType = f1//这里f1就是没参数名的函数
    f2() //函数调用
 
    //方式2,直接赋函数
    var f3 FuncType = func() {
        fmt.Printf("方式2:i = %d, str = %s\n", i, str)
    }
    f3() //函数调用= func() {
 
    //方式3,定义完了加()就是调用
    func() { //匿名函数,无参无返回值
        fmt.Printf("方式3:i = %d, str = %s\n", i, str)
    }() //别忘了后面的(), ()的作用是,此处直接调用此匿名函数
 
    //方式4, 匿名函数,有参有返回值
    v := func(a, b int) (result int) {
        result = a + b
        return
    }(1, 1) //别忘了后面的(1, 1), (1, 1)的作用是,此处直接调用此匿名函数, 并传参
    fmt.Println("v = ", v)
 
}

 

// --------------------------------------- 数组

var variable_name [SIZE]variable_type

var balance [10]float32

var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}//初始化

/* 未定义长度的数组只能传给不限制数组长度的函数 */

/* 定义了长度的数组只能传给限制了相同数组长度的函数 */

 

 

 

 

二维数组

var arrayName [ x ][ y ]variable_type

//初始化

a = [3][4]int{ 

 {0, 1, 2, 3} ,   /*  第一行索引为 0 */

 {4, 5, 6, 7} ,   /*  第二行索引为 1 */

 {8, 9, 10, 11},   /* 第三行索引为 2 */

}

 

 

 

// --------------------------------------- 结构体

type struct_variable_type struct {

   member definition;

   member definition;

   ...

   member definition;

}

 

type Books struct {

   title string

   author string

   subject string

   book_id int

}

 

// 创建一个新的结构体
fmt.Println(Books{"Go 语言", "www.runoob.com", "Go 语言教程", 6495407})
// 也可以使用 key => value 格式
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com", subject: "Go 语言教程", book_id: 6495407})
 
// 忽略的字段为 0 或 空
fmt.Println(Books{title: "Go 语言", author: "www.runoob.com"})

 

var Book1 Books        /* 声明 Book1 为 Books 类型 */

/* book 1 描述 */

Book1.title = "Go 语言"

Book1.author = "www.runoob.com"

Book1.subject = "Go 语言教程"

Book1.book_id = 6495407

 

// --------------------------------------- defer 延迟调用

关键字 defer ⽤于延迟一个函数或者方法(或者当前所创建的匿名函数)的执行。注意,defer语句只能出现在函数或方法的内部。
func main() {
    defer fmt.Println("this is a defer") //main结束前调用
fmt.Println("this is a test")
    /*
        运行结果:
        this is a test
        this is a defer
    */
}
 

defer语句经常被用于处理成对的操作,如打开、关闭、连接、断开连接、加锁、释放锁。通过defer机制,不论函数逻辑多复杂,都能保证在任何执行路径下,资源被释放。释放资源的defer应该直接跟在请求资源的语句后。

多个defer执行顺序

以LIFO(后进先出)的顺序执行。哪怕函数或某个延迟调用发生错误,这些调用依旧会被执⾏。

defer和匿名函数结合使用(注意里面的变量是否是闭包引用)

func main() {
    a, b := 10, 20
    defer func(x int) { // a以值传递方式传给x
        fmt.Println("defer:", x, b) // b 闭包引用,a是外部传参进来,已经传进来10,只是没执行
    }(a)
 
    a += 10
    b += 100
 
    fmt.Printf("a = %d, b = %d\n", a, b)
 
    /*
        运行结果:
        a = 20, b = 120
        defer: 10 120
    */
}

// --------------------------------------- 获取命令行参数

import (
    "fmt"
    "os"    //os.Args所需的包
)
func main() {
    args := os.Args //获取用户输入的所有参数,字符串
 
    //如果用户没有输入,或参数个数不够,则调用该函数提示用户
    if args == nil || len(args) < 2 {
        fmt.Println("err: xxx ip port")
        return
    }
    ip := args[1]   //获取输入的第一个参数
    port := args[2] //获取输入的第二个参数
fmt.Printf("ip = %s, port = %s\n", ip, port)
}

 

// ---------------------------------------不同作用域的同名变量

在不同作用域可以声明同名的变量,其访问原则为:在同一个作用域内,就近原则访问最近的变量,如果此作用域没有此变量声明,则访问全局变量,如果全局变量也没有,则报错。

 

 

基础数据类型

2.4.1 分类

Go语言内置以下这些基础类型:

类型

名称

长度

零值

说明

bool

布尔类型

1

false

其值不为真即为家,不可以用数字代表true或false

byte

字节型

1

0

uint8别名,放英文字符‘a’

rune

字符类型

4

0

专用于存储unicode编码,等价于uint32,可以放中文字符‘中’//20013

int, uint

整型

4或8

0

32位或64位

int8, uint8

整型

1

0

-128 ~ 127, 0 ~ 255

int16, uint16

整型

2

0

-32768 ~ 32767, 0 ~ 65535

int32, uint32

整型

4

0

-21亿 ~ 21 亿, 0 ~ 42 亿

int64, uint64

整型

8

0

 

float32

浮点型

4

0.0

小数位精确到7位

float64

浮点型

8

0.0

小数位精确到15位

complex64

复数类型

8

 

 

complex128

复数类型

16

 

 

uintptr

整型

4或8

 

⾜以存储指针的uint32或uint64整数

string

字符串

 

""

utf-8字符串,str[0]、str[1]

 

格式化输出输入

格式

含义

%%

一个%字面量

%b

一个二进制整数值(基数为2),或者是一个(高级的)用科学计数法表示的指数为2的浮点数

%c

字符型。可以把输入的数字按照ASCII码相应转换为对应的字符

%d

一个十进制数值(基数为10)

%e

以科学记数法e表示的浮点数或者复数值

%E

以科学记数法E表示的浮点数或者复数值

%f

以标准记数法表示的浮点数或者复数值

%g

以%e或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出

%G

以%E或者%f表示的浮点数或者复数,任何一个都以最为紧凑的方式输出

%o

一个以八进制表示的数字(基数为8)

%p

以十六进制(基数为16)表示的一个值的地址,前缀为0x,字母使用小写的a-f表示

%q

使用Go语法以及必须时使用转义,以双引号括起来的字符串或者字节切片[]byte,或者是以单引号括起来的数字

%s

字符串。输出字符串中的字符直至字符串中的空字符(字符串以'\0‘结尾,这个'\0'即空字符)

%t

以true或者false输出的布尔值

%T

使用Go语法输出的值的类型

%U

一个用Unicode表示法表示的整型码点,默认值为4个数字字符

%v

使用默认格式输出的内置或者自定义类型的值,或者是使用其类型的String()方式输出的自定义值,如果该方法存在的话

%x

以十六进制表示的整型值(基数为十六),数字a-f使用小写表示

%X

以十六进制表示的整型值(基数为十六),数字A-F使用小写表示

转载于:https://www.cnblogs.com/szgolang/p/9795633.html

你可能感兴趣的文章
织梦教程
查看>>
杭电多校 Harvest of Apples 莫队
查看>>
java 第11次作业:你能看懂就说明你理解了——this关键字
查看>>
C/C++心得-结构体
查看>>
函数名作为参数传递
查看>>
apt-get for ubuntu 工具简介
查看>>
数值计算算法-多项式插值算法的实现与分析
查看>>
day8-异常处理与网络编程
查看>>
Python基础-time and datetime
查看>>
Linux epoll 笔记(高并发事件处理机制)
查看>>
shell脚本练习01
查看>>
WPF图标拾取器
查看>>
通过取父级for循环的i来理解闭包,iife,匿名函数
查看>>
HDU 3374 String Problem
查看>>
数据集
查看>>
打印python包含汉字报SyntaxError: Non-ASCII character '\xe4' in file
查看>>
[Leetcode] unique paths ii 独特路径
查看>>
HDU 1217 Arbitrage (Floyd + SPFA判环)
查看>>
IntelliJ idea学习资源
查看>>
Django Rest Framework -解析器
查看>>