欢迎光临
感谢一路有你

学习go语言第二天

如果你对该文章中的内容有疑问/不解,可以点击此处链接提问
要注明问题和此文章链接地址 点击此处跳转
 

数组切片

数组 - 定长序列,声明时需要指定长度:


<code class="language-go">var arr [5]int
arr[0] = 1
arr[1] = 2
fmt.Println(arr)
// [1 2 0 0 0]

arr2 := [5]int{1, 2, 3, 4, 5}
fmt.Println(arr2)

</code>

切片 - 引用数组的可变长度片段:


<code class="language-go">slice := arr[1:3] // 创建切片 
slice = append(slice, 4) // 追加元素
fmt.Println(slice) //[2 0 4]
// 切片使用len()获取长度,cap()获取容量。
fmt.Println(len(slice), cap(slice)) // 3 4

</code>

for循环


<code class="language-go">// for循环遍历数组或切片:
for i := 0; i &lt; len(slice); i++ {
    fmt.Println(slice[i])
}
// 2
// 0
// 4


// for range遍历数组或切片:
for i, v := range arr {
    println(i, v)
}
// 0 1
// 1 2
// 2 0
// 3 4
// 4 0
</code>

其中range关键字可以遍历数组/切片,返回索引和值。
切片比数组更常用,可以灵活添加元素。我们通常用for range循环来遍历切片

流程控制

条件判断 - if语句:


<code class="language-go">x := 10
if x &gt; 10 {
    fmt.Println(&quot;x is greater than 10&quot;)
} else {  
    fmt.Println(&quot;x is less than 10&quot;)
}
</code>

多条件判断 - switch语句:


<code class="language-go">operatingSystem := &quot;linux&quot;
switch operatingSystem {
case &quot;darwin&quot;:
  fmt.Println(&quot;Mac OS&quot;)
case &quot;linux&quot;:
  fmt.Println(&quot;Linux&quot;)  
default:
  fmt.Println(&quot;Other System&quot;)
}
</code>

循环语句 - for循环:


<code class="language-go">    for i := 0; i &lt; 5; i++ {
        fmt.Println(i)
    }
</code>

循环控制语句:
continue:跳过当前循环,开始下一次循环
break:完全终止循环
goto:直接跳转到标签
defer语句 - 延迟调用:


<code class="language-go">defer fmt.Println(&quot;defer statement&quot;)
</code>

函数的使用

定义函数


<code class="language-go">func functionName(input1 type1, input2 type2) (output1 type1, output2 type2) {
  // 函数体代码
  return value1, value2 
}
</code>

函数参数:
可以有多个输入参数,按类型声明
可以有多个返回值,或无返回值
调用函数


<code class="language-go">result1, result2 := functionName(param1, param2)
</code>

匿名函数


<code class="language-go">func(paramType) returnType {
  // ...
}
</code>

闭包函数


<code class="language-go">func outer() func() {
  x := 10
  return func() {
    fmt.Println(x) 
  }
}
</code>

Go语言函数支持多参数、多返回值、匿名函数和闭包等特性,用法灵活。可以实现一类通用逻辑,提高代码复用性。

简单的算法程序


<code class="language-go">package main
import &quot;fmt&quot;


func AvgNum(nums ...int) int{
    var total int
    for _, num := range nums{
        total += num
    }
    return total / len(nums)
}
func AvgNum2(nums []int) int{
    var total int
    for _, num := range nums{
        total += num
    }
    return total / len(nums)
}

func main(){
    fmt.Println(AvgNum(1,2,3,4,5,6,7,8,9,10))
    fmt.Println(AvgNum2([]int{1,2,3,4,5,6,7,8,9,10}))

}
</code>

包管理

Go语言的包管理主要通过如下方式:

导入包
在代码顶部导入需要的包,如:


<code class="language-go">import &quot;fmt&quot;
import &quot;os&quot;
</code>

init()函数
包中的init()函数会在包加载时自动执行。

包作用域
函数名和变量名都是包级作用域,可以通过包名来访问。

包名约定
按照目录命名,同一个目录下的Go文件属于一个包。

包依赖管理
Go Modules来管理依赖版本,在Go 1.13+后是默认方式。

主要命令:

go mod init 初始化
go get 添加依赖
go mod tidy 整理依赖
go mod graph 查看依赖图
包的可见性
通过大写字母开头的导出名来控制对外可见性。

掌握了包的使用方法,可以组织代码结构,有效复用代码。

包的简单应用

好的,这里以编写一个数字计算的简单包为例:

  1. 在自己的工作区创建 calc 包目录:$GOPATH/src/calc

  2. 在该目录下创建calc.go文件:


<code class="language-go">package calc

func Add(a, b int) int {
  return a + b
}

func Sub(a, b int) int {
  return a - b  
}
</code>
  1. 在同一目录创建calc_test.go测试文件:

<code class="language-go">package calc

import &quot;testing&quot;

func TestAdd(t *testing.T) {
  if Add(1, 2) != 3 {
    t.Error(&quot;Add failed&quot;) 
  } 
}
</code>
  1. 其他程序可以通过导入这个包来使用:

<code class="language-go">import &quot;calc&quot;

calc.Add(1, 2) 
</code>
  1. 也可以为包起别名:

<code class="language-go">import c &quot;calc&quot; 

c.Add(1, 2)
</code>

以上演示了如何编写一个简单的包,包含函数、测试、导入使用等,可以作为练习包管理的示例。

structs和methods


<code class="language-go">package main
import &quot;fmt&quot;

// 定义一个User结构体 
type User struct {
    Id   int
    Name string
    Age  int
  }
  
  // 为User结构体定义方法
  func (u User) ToString() string {
    return fmt.Sprintf(&quot;User: %d %s %d&quot;, u.Id, u.Name, u.Age)
  }
  
  func main() {
    // 创建User对象
    user := User{Id: 1, Name: &quot;张三&quot;, Age: 23}
    
    // 调用method
    fmt.Println(user.ToString())
  }
</code>

输出:
User: 1 张三 23
这里定义了一个User结构体,包含了Id、Name和Age字段。
然后为User结构体定义了ToString方法,该方法可以输出用户信息。
在main函数中,我们创建了User对象user,然后就可以直接调用user.ToString()方法。
这样便实现了基于struct和method的面向对象编程。

指针


<code class="language-go">package main

import &quot;fmt&quot;

func main() {
  var a int = 10
  
  // 指针ptr指向a
  var ptr *int = &amp;a
  
  // 通过指针读取a的值
  fmt.Println(*ptr)
  
  // 通过指针修改a的值
  *ptr = 20
  
  fmt.Println(a)
}
示例解读:

声明变量a,初始值为10
声明指针ptr,存储变量a的地址 &amp;a
可以通过 deferencing *ptr 读取指针指向的变量值
通过指针ptr修改变量a的值为20
打印a输出20,说明指针ptr通过引用修改了a
指针是Go语言实现引用传递的基础。正确使用指针可以在函数间传递引用而不仅是拷贝值。
</code>

map

这里是一个Go语言中map使用的简单示例:


<code class="language-go">package main

import &quot;fmt&quot;

func main() {
  // 创建map
  ages := make(map[string]int)
  
  // 添加键值对
  ages[&quot;Alice&quot;] = 25
  ages[&quot;Bob&quot;] = 30
  
  // 读取数据
  fmt.Println(ages[&quot;Alice&quot;])
  
  // 遍历map
  for name, age := range ages {
    fmt.Println(name, age)
  }
  
  // 判断某键是否存在
  _, ok := ages[&quot;Charlie&quot;]
  if !ok {
    fmt.Println(&quot;Charlie not found&quot;) 
  }
}


示例解读:

1. 使用make创建map,键是字符串,值是int

2. 通过 key=value 语法插入键值对

3. 通过 key 读取值,如果不存在则返回值类型的零值

4. 可以遍历map获取到所有的键值对

5. 用value, ok := map[key]判断key是否存在

map是Go语言内建的哈希表实现,可以通过键快速查找值,非常实用。

</code>

为什么要使用匿名变量

在Go语言中,使用 _ 下划线声明的变量为匿名变量,通常用于忽略不需要的返回值。
在判断map中键是否存在的示例代码中:


<code class="language-go">_, ok := ages[&quot;Charlie&quot;]
</code>

map在访问一个键时会返回两个值,第一个值是该键对应的值,第二个值是一个布尔值,表示该键是否存在。
这里我们不需要访问的值,只需要知道该键是否存在。所以使用 _ 忽略了第一个返回值,只获取了第二个返回值ok,来判断键是否存在。
如果写成:


<code class="language-go">value, ok := ages[&quot;Charlie&quot;] 
</code>

那么value会获取到值类型的零值。我们不需要value变量,所以使用匿名变量_忽略第一个返回值,这样代码更简洁。

所以Go语言中的匿名变量_ 主要用于丢弃不需要的返回值,从而简化代码。

赞(1) 打赏
未经允许不得转载:王明昌博客 » 学习go语言第二天
分享到: 更多 (0)

相关推荐

  • 暂无文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

×
订阅图标按钮