Go语言入门学习记录

源自:Go语言教程

1、Go语言初识

1.1、Go 语言用途

Go 语言被设计成一门应用于搭载Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。对于高性能分布式系统领域而言,Go语言无疑比大多数其它语言有着更高的开发效率。它提供了海量并行的支持,这对于游戏服务端的开发而言是再好不过了。

学习记录:Go语言在搭载Web服务器和高性能分布式系统领域较其他语言具有更高的开发效率 。且支持并行计算 。适用于游戏服务器开发。

1.1.1第一个 Go 程序

接下来我们来编写第一个 Go程序 hello.go(Go语言源文件的扩展是 .go),代码如下:

hello.go 文件
package main
import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

要执行 Go语言代码可以使用go run 命令。
执行以上代码输出:

$ go run hello.go 
Hello, World!

此外我们还可以使用go build命令来生成二进制文件:

$ go build hello.go 
$ ls
hello    hello.go
$ ./hello 
Hello, World!

学习记录:
执行和生成二进制文件

go run hello.go
go bulid hello.go

1.2、Go语言环境

安装包下载地址为:https://golang.org/dl/。

系统安装包
Windowsgo1.4.windows-amd64.msi
Linuxgo1.4.linux-amd64.tar.gz
Macgo1.4.darwin-amd64-osx10.8.pkg
FreeBSDgo1.4.freebsd-amd64.tar.gz

学习记录:安装基于windows的Go语言开发环境。将 e:\Go\bin目录添加到 path 环境变量中。桌面新建一个记事本文件,将以下代码输入,保存文件为hello.go

package main

import "fmt"

func main() {
   fmt.Println("Hello, World!")
}

在相应的工作区E:/Go 执行脚本语言 go run hello.go
添加后你需要重启命令窗口才能生效

2、Go语言结构

2.1、行分隔符

在 Go 程序中,一行代表一个语句结束。每个语句不需要像 C家族中的其它语言一样以分号 ; 结尾,因为这些工作都将由Go编译器自动完成。
以下为两个语句:

fmt.Println("Hello, World!")
fmt.Println("Hello, Golang!")

学习记录:Go语言不同于C家族的其他语言,不需要;结尾

2.2、标识符

当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 protected )。

学习记录:标识符大小写相当于面向对象语言中的public和protected,体现为使用它的包对外是否可见。

2.2.1、空白标识符在函数返回值时的使用

package main

import "fmt"

func main() {
  _,numb,strs := numbers() //只获取函数返回值的后两个
  fmt.Println(numb,strs)
}

//一个可以返回多个值的函数
func numbers()(int,int,string){
  a , b , c := 1 , 2 , "str"
  return a,b,c
}

输出:

2 str

2.3、“{”不能单独放在一行

需要注意的是 { 不能单独放在一行,所以以下代码在运行时会产生错误:

package main

import "fmt"

func main()  
{  // 错误,{ 不能在单独的行上
    fmt.Println("Hello, World!")
}

2.4、导入包

Go 语言的包引入一般为: 项目名/包名

import "test/controllers"

可以省略import导入多个非main包

import (
    "fmt"
    "math"
)

2.5、更改包的别名

这里将包fmt改为别名.,代表省略模块名称,直接调用方法即可

import . "fmt"
func main (){
    Println("hello,world")
}

2.6、声明

通过 const 关键字来进行常量的定义。

// 常量定义
const PI = 3.14

通过在函数体外部使用 var 关键字来进行全局变量的声明和赋值。

// 全局变量的声明和赋值
var name = "gopher"

通过 type 关键字来进行结构(struct)和接口(interface)的声明。

// 一般类型声明
type newType int

// 结构的声明
type gopher struct{}

// 接口的声明
type golang interface{}

通过 func 关键字来进行函数的声明。

// 由main函数作为程序入口点启动
func main() {
    Println("Hello World!")
}

学习记录:type用法和全局变量的用法

3、Go基础语法

学习记录:这一部分是每个语法都会涉及的基础,简单过一遍,通过一个个例子来学习,并将不同于C语言家族的部分加以强调

3.1、标识符

标识符用来命名变量、类型等程序实体。一个标识符实际上就是一个或是多个字母(AZ和az)数字(0~9)、下划线_组成的序列,但是第一个字符必须是字母或下划线而不能是数字。
如:

mahesh   kumar   abc   move_name   a_123
myname50   _temp   j   a23b9   retVal

学习记录:标识符的第一个字符不能是数字

3.2、字符串连接

Go 语言的字符串可以通过 + 实现:

package main
import "fmt"
func main() {
    fmt.Println("Google" + "Runoob")
}

输出:

GoogleRunoob

学习记录:这个和 Java 类似

3.3、格式化字符串

package main

import "fmt"

func main() {
    fmt.Println(fmt.Sprintf("Code=%d&endDate=%s",123,"2020-12-31"))
}

输出:

Code=123&endDate=2020-12-31

3.4、数字类型

Go 也有基于架构的类型,例如:int、uint 和 uintptr。

序号类型和描述
uint8无符号 8 位整型 (0 到 255)
uint16无符号 16 位整型 (0 到 65535)
uint32无符号 32 位整型 (0 到 4294967295)
uint64无符号 64 位整型 (0 到 18446744073709551615)
int8有符号 8 位整型 (-128 到 127)
int16有符号 16 位整型 (-32768 到 32767)
int32有符号 32 位整型 (-2147483648 到 2147483647)
int64有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)

浮点型

序号类型和描述
float32IEEE-754 32位浮点型数
float64IEEE-754 64位浮点型数
complex6432 位实数和虚数
complex12864 位实数和虚数

以下列出了其他更多的数字类型:

序号类型和描述
byte类似 uint8
rune类似 int32
uint32 或 64 位
int与 uint 一样大小
uintptr无符号整型,用于存放一个指针

学习记录:complex,rune,uintptr三项新认识,分别表示实数或虚数、int32和 无符号整数指针

3.5、变量

①、多变量赋值
示例1:

package main
import . "fmt"
func main() {
    var a string = "Runoob"
    Println(a)

    var b, c int = 1, 2
    Println(b, c)
}

输出:

Runoob
1 2

②、默认初始化

示例2:

package main
import "fmt"
func main() {

    // 声明一个变量并初始化
    var a = "RUNOOB"//根据值自行判定变量类型。
    fmt.Println(a)

    // 没有初始化就为零值
    var b int
    fmt.Println(b)

    // bool 零值为 false
    var c bool
    fmt.Println(c)

	//字符串 零值为“” (空字符串)
	var d string
	fmt.Println(d)
}

输出:

RUNOOB
0
false

③、声明变量
intVal := 1 相等于:

var intVal int 
intVal =1

3.6、常量

常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型

①、常量可以用作枚举:

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

数字 0、1 和 2 分别代表未知性别、女性和男性。

②、常量可以用len(), cap(), unsafe.Sizeof()函数计算表达式的值。常量表达式中,函数必须是内置函数,否则编译不过:

实例:

package main

import "unsafe"
const (
    a = "abc"
    b = len(a)
    c = unsafe.Sizeof(a)
)

func main(){
    println(a, b, c)
}

输出:

abc 3 16

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

iota用法:

package main

import "fmt"

func main() {
    const (
            a = iota   //0
            b          //1
            c          //2
            d = "ha"   //独立值,iota += 1
            e          //"ha"   iota += 1
            f = 100    //iota +=1
            g          //100  iota +=1
            h = iota   //7,恢复计数
            i          //8
    )
    fmt.Println(a,b,c,d,e,f,g,h,i)
}

输出 :

0 1 2 ha ha 100 100 7 8

再看个有趣的的 iota 实例:

package main

import "fmt"
const (
    i=1<<iota
    j=3<<iota
    k
    l
)

func main() {
    fmt.Println("i=",i)
    fmt.Println("j=",j)
    fmt.Println("k=",k)
    fmt.Println("l=",l)
}

输出:

i= 1
j= 6
k= 12
l= 24

iota 表示从 0 开始自动加 1,所以 i=1<<0, j=3<<1(<< 表示左移的意思),即:i=1, j=6,这没问题,关键在 k 和 l,从输出结果看 k=3<<2,l=3<<3。
简单表述:
i=1:左移 0 位,不变仍为 1。
j=3:左移 1 位,变为二进制 110,即 6。
k=3:左移 2 位,变为二进制 1100,即 12。
l=3:左移 3 位,变为二进制 11000,即 24。

3.7、运算符

有些运算符拥有较高的优先级,二元运算符的运算方向均是从左至右。下表列出了所有运算符以及它们的优先级,由上至下代表优先级由高到低:

优先级运算符
5* / % << >> & &^
4+ -
3== != < <= > >=
2逻辑与运算
1逻辑或运算

3.8、条件语句

①、if…else

if 布尔表达式 {
   /* 在布尔表达式为 true 时执行 */
} else {
  /* 在布尔表达式为 false 时执行 */
}

②、switch

switch var1 {
    case val1:
        ...
    case val2:
        ...
    default:
        ...
}

③、select
select 是 Go 中的一个控制结构,类似于用于通信的 switch 语句。每个 case 必须是一个 Channel 的收发操作。
select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。一个默认的子句应该总是可运行的。
Go 编程语言中 select 语句的语法如下:

select {
    case communication clause  :
       statement(s);      
    case communication clause  :
       statement(s);
    /* 你可以定义任意数量的 case */
    default : /* 可选 */
       statement(s);
}

学习记录:注意条件不带()

3.9、循环语句

①、for循环
计算 1 到 10 的数字之和:

package main

import "fmt"

func main() {
        sum := 0
        for i := 0; i <= 10; i++ {
                sum += i
        }
        fmt.Println(sum)
}

输出结果为:

55

②、For-each range 循环
这种格式的循环可以对字符串、数组、切片等进行迭代输出元素。

package main
import "fmt"

func main() {
        strings := []string{"google", "runoob"}
        for i, s := range strings {
                fmt.Println(i, s)
        }

        numbers := [6]int{1, 2, 3, 5}
        for i,x:= range numbers {
                fmt.Printf("第 %d 位 x 的值 = %d\n", i,x)
        }  
}

输出:

0 google
1 runoob
第 0 位 x 的值 = 11 位 x 的值 = 22 位 x 的值 = 33 位 x 的值 = 54 位 x 的值 = 05 位 x 的值 = 0

学习记录:For-each range 循环可以同时获取值和序号

3.10、函数

①、Go 语言函数定义格式如下:

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

函数定义解析:

func:函数由 func 开始声明
function_name:函数名称,参数列表和返回值类型构成了函数签名。
parameter list:参数列表,参数就像一个占位符,当函数被调用时,你可以将值传递给参数,这个值被称为实际参数。参数列表指定的是参数类型、顺序、及参数个数。参数是可选的,也就是说函数也可以不包含参数。
return_types:返回类型,函数返回一列值。return_types 是该列值的数据类型。有些功能不需要返回值,这种情况下return_types 不是必须的。
函数体:函数定义的代码集合。

以下实例为 max() 函数的代码,该函数传入两个整型参数 num1 和 num2,并返回这两个参数的最大值:

func max(num1, num2 int) int {
   /* 声明局部变量 */
   var result int

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

输出:

200

②、函数返回多个值
Go 函数可以返回多个值,例如:

package main

import "fmt"

func swap(x, y string) (string, string) {
   return y, x
}

func main() {
   a, b := swap("Google", "Runoob")
   fmt.Println(a, b)
}

输出:

Runoob Google

③、函数参数
函数如果使用参数,该变量可称为函数的形参。
形参就像定义在函数体内的局部变量。
调用函数,可以通过两种方式来传递参数:

传递类型 描述

  • 值传递 值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
  • 引用传递 引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
    默认情况下,Go 语言使用的是值传递,即在调用过程中不会影响到实际参数

学习记录:默认情况下是值传递,调用过程中不会影响实参;可以返回多个值。函数调用结果可以作为另一个函数的实参。

3.11、闭包

Go 语言支持匿名函数,可作为闭包。匿名函数是一个"内联"语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。

以下实例中,我们创建了函数 getSequence() ,返回另外一个函数。该函数的目的是在闭包中递增 i 变量,代码如下:

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())
}

输出:

1
2
3
1
2

学习记录:闭包是匿名函数,可在动态编程中使用

先更新到这里,剩余部分本周择时学习

剩余部分为

  • 数组
  • 指针
  • 结构体
  • 切片
  • Range
  • Map
  • 递归
  • 类型转换
  • 语言接口
  • 错误处理
  • 并发
  • go语言开发工具
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

疯狂java杰尼龟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值