GO学习记录

一、Go语言的源文件的拓展是.go

        开发环境和工具:GOLAND

个人版开发:

企业版开发:

二、Go语言结构

        1、package main  定义一个名为main的包名

        2、import "fmt"    添加fmt包

        3、func main()    是程序开始执行的函数

        4、定义变量:var  a  int  =  21  (和C不同,变量名放在了变量类型前面)

        5、//单行注释     /*......*/多行注释

  在goland编辑器中
    单行注释的快捷键是    Ctrl+/
    多行注释的快捷键是    Alt+Shift+/

        6、fmt.Println(...) 可以将字符串输出到控制台,并在最后自动增加换行字符 \n

        7、当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:

                Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序

                需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小

                写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面

                向对象语言中 的 protected )

        注:

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

三、Go语言风格

        1.程序一般由关键字、常量、变量、运算符、类型和函数组成

        2.Go 语言变量名由字母、数字、下划线组成,其中首个字符不能为数字。

            声明变量的一般形式是使用 var 关键字:

        3.常量是一个简单值的标识符,在程序运行时,不会被修改的量。

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

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

       多重赋值const a, b, c = 1, false, "str" //多重赋值

                    多个相同类型的声明可以简写为:const c_name1, c_name2 = value1, value2

        4.常量还可以用作枚举:

const (
    Unknown = 0
    Female = 1
    Male = 2
)
数字 0、1 和 2 分别代表未知性别、女性和男性。

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

        5.iota,特殊常量,可以认为是一个可以被编译器修改的常量。

                iota 在 const关键字出现时将被重置为 0(const 内部的第一行之前),const 中每新增一行

                常量声明将使 iota 计数一次(iota 可理解为 const 语句块中的行索引)。

                iota 可以被用作枚举值:

const (
    a = iota
    b = iota
    c = iota
)
第一个 iota 等于 0,每当 iota 在新的一行被使用时,它的值都会自动加 1;
所以 a=0, b=1, c=2 可以简写为如下形式:

const (
    a = iota
    b
    c
)

实例

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

        6.Go的算数运算符    A=10,B=20

运算符 描述 实例
+ 相加 A + B 输出结果 30
- 相减 A - B 输出结果 -10
* 相乘 A * B 输出结果 200
/ 相除 B / A 输出结果 2
% 求余 B % A 输出结果 0
++ 自增 A++ 输出结果 11
-- 自减 A-- 输出结果 9

        7.Go的关系运算符    A=10,B=20

运算符 描述 实例
== 检查两个值是否相等,如果相等返回 True 否则返回 False。 (A == B) 为 False
!= 检查两个值是否不相等,如果不相等返回 True 否则返回 False。 (A != B) 为 True
> 检查左边值是否大于右边值,如果是返回 True 否则返回 False。 (A > B) 为 False
< 检查左边值是否小于右边值,如果是返回 True 否则返回 False。 (A < B) 为 True
>= 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。 (A >= B) 为 False
<= 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。 (A <= B) 为 True

        8.Go的逻辑运算符

运算符 描述 实例
&& 逻辑 AND 运算符。 如果两边的操作数都是 True,则条件 True,否则为 False。 (A && B) 为 False
|| 逻辑 OR 运算符。 如果两边的操作数有一个 True,则条件 True,否则为 False。 (A || B) 为 True
! 逻辑 NOT 运算符。 如果条件为 True,则逻辑 NOT 条件 False,否则为 True。 !(A &

        9.Go的位运算符

Go 语言支持的位运算符如下表所示。假定 A 为60,B 为13:

运算符 描述 实例
& 按位与运算符"&"是双目运算符。 其功能是参与运算的两数各对应的二进位相与。 (A & B) 结果为 12, 二进制为 0000 1100
| 按位或运算符"|"是双目运算符。 其功能是参与运算的两数各对应的二进位相或 (A | B) 结果为 61, 二进制为 0011 1101
^ 按位异或运算符"^"是双目运算符。 其功能是参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (A ^ B) 结果为 49, 二进制为 0011 0001
<< 左移运算符"<<"是双目运算符。左移n位就是乘以2的n次方。 其功能把"<<"左边的运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。 A << 2 结果为 240 ,二进制为 1111 0000
>> 右移运算符">>"是双目运算符。右移n位就是除以2的n次方。 其功能是把">>"左边的运算数的各二进位全部右移若干位,">>"右边的数指定移动的位数。 A >> 2 结果为 15 ,二进制为 0000 1111

        10.Go的赋值运算符

运算符 描述 实例
= 简单的赋值运算符,将一个表达式的值赋给一个左值 C = A + B 将 A + B 表达式结果赋值给 C
+= 相加后再赋值 C += A 等于 C = C + A
-= 相减后再赋值 C -= A 等于 C = C - A
*= 相乘后再赋值 C *= A 等于 C = C * A
/= 相除后再赋值 C /= A 等于 C = C / A
%= 求余后再赋值 C %= A 等于 C = C % A
<<= 左移后赋值 C <<= 2 等于 C = C << 2
>>= 右移后赋值 C >>= 2 等于 C = C >> 2
&= 按位与后赋值 C &= 2 等于 C = C & 2
^= 按位异或后赋值 C ^= 2 等于 C = C ^ 2
|= 按位或后赋值 C |= 2 等于 C = C | 2

11.Go的其它运算符

下表列出了Go语言的其他运算符。

运算符 描述 实例
& 返回变量存储地址 &a; 将给出变量的实际地址。
* 指针变量。 *a; 是一个指针变量

12.Go的运算符优先级

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

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

四、Go语言条件语句

1.if语句

(if 语句 由一个布尔表达式后紧跟一个或多个语句组成)

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

例子:
package main

import "fmt"

func main() {
   /* 定义局部变量 */
   var a int = 10
 
   /* 使用 if 语句判断布尔表达式 */
   if a < 20 {
       /* 如果条件为 true 则执行以下语句 */
       fmt.Printf("a 小于 20\n" )
   }
   fmt.Printf("a 的值为 : %d\n", a)
}

以上代码执行结果为:

a 小于 20
a 的值为 : 10

2.if..else语句

(if 语句后可以使用可选的else语句,else语句中的表达式在布尔表达式为 false 时执行)

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

例子:
package main

import "fmt"

func main() {
   /* 局部变量定义 */
   var a int = 100;
 
   /* 判断布尔表达式 */
   if a < 20 {
       /* 如果条件为 true 则执行以下语句 */
       fmt.Printf("a 小于 20\n" );
   } else {
       /* 如果条件为 false 则执行以下语句 */
       fmt.Printf("a 不小于 20\n" );
   }
   fmt.Printf("a 的值为 : %d\n", a);

}

以上代码执行结果为:

a 不小于 20
a 的值为 : 100

3.if嵌套语句

(可以在 if 或 else if 语句中嵌入一个或多个 if 或 else if 语句)

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

例子:
package main

import "fmt"

func main() {
   /* 定义局部变量 */
   var a int = 100
   var b int = 200
 
   /* 判断条件 */
   if a == 100 {
       /* if 条件语句为 true 执行 */
       if b == 200 {
          /* if 条件语句为 true 执行 */
          fmt.Printf("a 的值为 100 , b 的值为 200\n" );
       }
   }
   fmt.Printf("a 值为 : %d\n", a );
   fmt.Printf("b 值为 : %d\n", b );
}

以上代码执行结果为:

a 的值为 100 , b 的值为 200
a 值为 : 100
b 值为 : 200

4.switch语句

( 用于基于不同条件执行不同动作)

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

实例:
package main

import "fmt"

func main() {
   /* 定义局部变量 */
   var grade string = "B"
   var marks int = 90

   switch marks {
      case 90: grade = "A"
      case 80: grade = "B"
      case 50,60,70 : grade = "C"
      default: grade = "D"  
   }

   switch {
      case grade == "A" :
         fmt.Printf("优秀!\n" )    
      case grade == "B", grade == "C" :
         fmt.Printf("良好\n" )      
      case grade == "D" :
         fmt.Printf("及格\n" )      
      case grade == "F":
         fmt.Printf("不及格\n" )
      default:
         fmt.Printf("差\n" );
   }
   fmt.Printf("你的等级是 %s\n", grade );      
}

以上代码执行结果为:

优秀!
你的等级是 A

         switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际存储的变量类型。

Type Switch 语法格式如下:

switch x.(type){
    case type:
       statement(s);      
    case type:
       statement(s); 
    /* 你可以定义任意个数的case */
    default: /* 可选 */
       statement(s);
}
实例
package main

import "fmt"

func main() {
   var x interface{}
     
   switch i := x.(type) {
      case nil:  
         fmt.Printf(" x 的类型 :%T",i)                
      case int:  
         fmt.Printf("x 是 int 型")                      
      case float64:
         fmt.Printf("x 是 float64 型")          
      case func(int) float64:
         fmt.Printf("x 是 func(int) 型")                      
      case bool, string:
         fmt.Printf("x 是 bool 或 string 型" )      
      default:
         fmt.Printf("未知型")    
   }  
}
以上代码执行结果为:

x 的类型 :<nil>

         使用 fallthrough 会强制执行后面的 case 语句,fallthrough 不会判断下一条 case 的表达式结果是否为 true。

实例
package main

import "fmt"

func main() {

    switch {
    case false:
            fmt.Println("1、case 条件语句为 false")
            fallthrough
    case true:
            fmt.Println("2、case 条件语句为 true")
            fallthrough
    case false:
            fmt.Println("3、case 条件语句为 false")
            fallthrough
    case true:
            fmt.Println("4、case 条件语句为 true")
    case false:
            fmt.Println("5、case 条件语句为 false")
            fallthrough
    default:
            fmt.Println("6、默认 case")
    }
}
以上代码执行结果为:

2、case 条件语句为 true
3、case 条件语句为 false
4、case 条件语句为 true

        总结从以上代码输出的结果可以看出:switch 从第一个判断表达式为 true 的 case 开始执行,如果 case 带有 fallthrough,程序会继续执行下一条 case,且它不会去判断下一个 case 的表达式是否为 true。 

5.select语句

(select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行 )

select {
  case <- channel1:
    // 执行的代码
  case value := <- channel2:
    // 执行的代码
  case channel3 <- value:
    // 执行的代码

    // 你可以定义任意数量的 case

  default:
    // 所有通道都没有准备好,执行的代码
}

实例::::::
package main

import (
    "fmt"
    "time"
)

func main() {
    // 定义两个通道
    c1 := make(chan string)
    c2 := make(chan string)

    // 启动两个 goroutine(协程),分别从两个通道中获取数据
    go func() {
        time.Sleep(1 * time.Second)
        c1 <- "one"
    }()
    go func() {
        time.Sleep(2 * time.Second)
        c2 <- "two"
    }()
    
    // 使用 select 语句非阻塞地从两个通道中获取数据
    for i := 0; i < 2; i++ {
        select {
        case msg1 := <-c1:
            fmt.Println("received", msg1)
        case msg2 := <-c2:
            fmt.Println("received", msg2)
        //default:
             如果两个通道都没有可用的数据,则执行这里的语句
            //fmt.Println("no message received")
        }
    }
}


以上代码执行结果为:

received one
received two

五、Go语言循环语句

1. for循环语句 (重复执行语句块)

        for循环的三种形式:

①.和C一样

for init; condition; post { }

②.和C的while一样

for condition { }

③.和C的for(;;)一样

for { }
  • init: 一般为赋值表达式,给控制变量赋初值;
  • condition: 关系表达式或逻辑表达式,循环控制条件;
  • post: 一般为赋值表达式,给控制变量增量或减量。

 六、Go语言函数

go语言的函数格式:

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


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


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语言数组

1.基础知识:数组元素可以通过索引(位置)来读取(或者修改),索引从 0 开始,第一个元素索引为 0,第二个索引为 1

2.声明数组:

Go 语言数组声明需要指定元素类型及元素个数,语法格式如下:

var variable_name [SIZE] variable_type

实例:var balance [10] float32

3.初始化数组:

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

balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}

1.如果数组长度不确定,可以使用 ... 代替数组的长度,编译器会根据元素个数自行推断数组的长度:

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

2.如果设置了数组的长度,我们还可以通过指定下标来初始化元素:

//  将索引为 1 和 3 的元素初始化
balance := [5]float32{1:2.0,3:7.0}

注:初始化数组中 {} 中的元素个数不能大于 [] 中的数字/如果忽略 [] 中的数字不设置数组大小,Go 语言会根据元素的个数来设置数组的大小

八、Go语言指针

        说明:一个指针变量指向了一个值的内存地址

声明格式如下:

var var_name *var-type

实例:这是一个指向 int 和 float32 的指针
var ip *int        /* 指向整型*/
var fp *float32    /* 指向浮点型 */

九、Go语言切片(简单来说就是动态数组,数组长度可变)

1.定义切片

        ①声明一个未指定大小的数组(切片不需要说明长度)

var identifier [ ]type

        ②使用make 函数来创建切片

var slices [ ]type = make([ ] type,len)

简写:slices := make([ ]type,len)

        ③指容量,其中capacity为可数参数

make([ ]T,length,capacity)

2.切片初始化

①直接初始化切片,[ ]表示切片类型,初始化值依次为1,2,3,其中cap = len = 3

s := [ ]int {1,2,3}

②初始化切片s,是数组arr的引用

s := arr[ : ] 

 ③将数组从下标索引startindex到endindex-1下的元素创建为一个新的切片

s := arr[ startIndex:endIndex ]

④默认endIndex时将表示一直到arr数组最后一个元素表示为一个切片

s := arr[startIndex :]

⑤默认startIndex时将表示从arr的第一个元素开始

s:= arr[ : endIndex]

⑥通过切片s初始化切片s1

s1 = s[startIndex : endIndex]

⑦通过内置函数make()初始化切片s,[]int标识为其元素类型类型为int的切片

s := make([ ]int,len,cap) 

十、结构体字段命名及使用范围

package main

import "fmt"

// 定义一个名为 Person 的结构体
type Person struct {
    Name string // 可导出的字段
    age  int    // 私有的字段
}

func main() {
    // 创建 Person 结构体的实例
    p := Person{
        Name: "Alice",
        age:  25,
    }

    fmt.Println(p.Name) // 可以访问可导出的字段
    // fmt.Println(p.age)  // 无法访问私有的字段,会编译错误
}

十一、goland的重构快捷键

十一、函数和接口的区别

  • 函数是一段可执行的代码块,用于实现特定的功能,而接口是一种抽象的类型,用于定义一组方法的集合。
  • 函数可以独立定义和调用,而接口需要被类型实现才能使用。
  • 函数可以接收参数和返回结果,而接口只定义方法的签名,不包含具体的实现。
  • 函数通常用于封装可重用的代码逻辑,而接口用于定义多个类型之间的共享行为。

可以使用以下生动的比喻来说明它们之间的区别:

想象一下你是一家快递公司的老板,而函数就像是你的员工,而接口则是你制定的一套操作规范。

  • 函数(function)就像是你的员工。每个函数都是一个独立的工作人员,他们各自有自己的任务和职责。你可以将特定的任务分配给不同的函数,并在需要时调用他们。每个函数相当于执行某项具体任务的工人。

  • 接口(interface)就像是你制定的操作规范。接口是一套定义了一组方法的规则,描述了工人应该具备的共同行为。你可以制定一份规范,例如所有的工人都必须具备“送货”和“签收”这两种行为。每个工人只要按照规范实现这两个方法,就可以成为符合规范的工人。

使用快递公司的例子,可以更容易理解函数和接口的区别。函数就像是具体的工人,而接口则是定义了工人应该有的共同行为的规范。这样,你可以根据具体的需求,雇佣不同的工人来完成不同的任务。而接口规范则确保了无论是哪位工人,他们都能完成规定的任务,从而保证了快递服务的质量和一致性。

相关推荐

  1. GO 语言基础学习记录

    2023-12-29 09:46:04       35 阅读
  2. GO 语言基础学习记录(二)

    2023-12-29 09:46:04       40 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-29 09:46:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-29 09:46:04       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-29 09:46:04       82 阅读
  4. Python语言-面向对象

    2023-12-29 09:46:04       91 阅读

热门阅读

  1. 多线程多进程的使用场景和常见问题处理

    2023-12-29 09:46:04       57 阅读
  2. MySQL数据库索引

    2023-12-29 09:46:04       62 阅读
  3. Presentation Error:编程中的细节之战

    2023-12-29 09:46:04       52 阅读
  4. 获取请求的真实ip

    2023-12-29 09:46:04       55 阅读
  5. opencv c++圆检测

    2023-12-29 09:46:04       55 阅读
  6. Docker Compose容器编排实战

    2023-12-29 09:46:04       55 阅读
  7. PHP:服务器端脚本语言的瑰宝

    2023-12-29 09:46:04       51 阅读
  8. axios如何在vue中使用

    2023-12-29 09:46:04       53 阅读
  9. 基于技能的简历:求职的战略方法

    2023-12-29 09:46:04       65 阅读
  10. 在简历中评价和体现技能水平的最佳方式

    2023-12-29 09:46:04       59 阅读
  11. vue3面试题

    2023-12-29 09:46:04       48 阅读
  12. (Qt) 预编译头文件precompile_header

    2023-12-29 09:46:04       53 阅读