GO 语言基础学习记录(二)

//这里记录一些在学习golang语言基础的时候,发现的一些容易记错的特殊情况,后续发现其他的再补充。

一、变量和数据方面

1.切片和map引用类型

问题描述:在go中,切片和map是引用类型,所以当修改切片值的时候,会同步修改到原数据中,下面用切片数据进行演示

package main

import (
        "fmt"
)

func main() {
        var arr []int = []int{1,2,3,4,5}   // 声明一个切片数据
        fmt.Println(arr)                       // [1 2 3 4 5]
        tarr := arr[1:4]                        // 针对arr数据进行切片获取
        fmt.Println(tarr)                      // [2 3 4]
        tarr[2] = 22                            // 赋值切片数据
        fmt.Println(arr)                      // [1 2 3 22 5]
        fmt.Println(tarr)                     // [2 3 22]
}

2.结构体间比较

问题描述:在 Go 语言中,Go 结构体有时候并不能直接比较,当其基本类型包含:slice、map、function 时,是不能比较的。若强行比较,就会导致出现报错

3.遗漏的byte和rune类型

问题描述:记录下遗漏的byte和rune类型

byte: uint8类型,或者叫 byte 型,代表了ASCII码的一个字符。(比如: a输出就是)

rune: rune类型,代表一个 UTF-8字符。

package main

import (
        "fmt"
)

func main() {
        s := "www.huixiong.com博客"                        //设定字符串
        for i := 0; i < len(s); i++ {   //byte
                fmt.Printf("%v(%c) ", s[i], s[i])                //输出字符串中对应的ASCII码和字符
        }
        fmt.Println()
        for _, r := range s { //rune
                fmt.Printf("%v(%c) ", r, r)                        //输出字符串中对应的ASCII码和字符
        }
        fmt.Println()
}

4.数组和切片

  1. 切片容量可伸缩;数组容量不可变;
  2. 切片与切片不可比较,切片只能与nil比较;数组之间可以比较;
  3. 当切片原有空间不足时,且切片原有空间<1024,那么切片的空间将会直接翻倍。如原切片空间为3,则空间不足时,go会直接扩展为6

二、变量与作用域方面

1.语句中声明变量的作用域

问题描述:即使在同一函数中,在if、for等语句中声明的变量,都是全新且作用于该语句内(类似语句中的局部变量)。

package main

import (
        "fmt"
)

func main() {
        i, j := 0, 0                                                // 赋值 i,j 为0
        if true {
                fmt.Printf("i = %d, j = %d\n", i, j)    // i = 0, j = 0
                i, j := 1, 1                                        // 新变量 i,j 赋值为1
                fmt.Printf("i = %d, j = %d\n", i, j)    // i = 1, j = 1
        }
        fmt.Printf("i = %d, j = %d\n", i, j)            // i = 0, j = 0
        for k := 0 ; k < 1; k++ {
                fmt.Printf("i = %d, j = %d\n", i, j)    // i = 0, j = 0
                i, j := 2, 2                                       // 新变量 i,j 赋值为2
                fmt.Printf("i = %d, j = %d\n", i, j)   //i = 2, j = 2
        }
        fmt.Printf("i = %d, j = %d\n", i, j)           // i = 0, j = 0
}

 三、函数和方法方面

1.函数可变参数

问题描述:函数中有可变参数传入,如下代码所示

package main

import (
        "fmt"
)

func main() {
        fmt.Println(sum(1))
        fmt.Println(sum(1,2,3))
}

func sum(nums ...int)int{         //形参和类型中间用...来声明 可变参数,如果不传则为nil
        fmt.Println("len of nums is : ", len(nums))
        res := 0
        for _, v := range nums{
                res += v
        }
        return res
}

注意:1.当函数形参用...声明为可变参数时,如果不传入参数则 nums 的值为nil。2. 可变参数必须在函数参数列表的尾部,即最后一个(如放前面会引起编译时歧义)

2.main和init的区别

问题描述:在go中,除了默认入口函数(主函数) main 以外,还有个初始化包(package)的 init 函数。

相同点:(init和main)两个函数在定义时不能有任何的参数和返回值,且Go程序自动调用。
不同点:init可以应用于任意包中,且可以重复定义多个。main函数只能用于main包中,且只能定义一个。

3.匿名函数

问题描述:记录一下匿名函数,匿名函数是指不需要定义函数名的一种函数实现方式。

package main

import (
        "fmt"
)

func main() {
        getSqrt := func(a float64) float64 {                //声明匿名函数
                return math.Sqrt(a)
        }
        fmt.Println(getSqrt(4))
}

 4.闭包函数

问题描述:记录下go语言中的 闭包函数,闭包是由函数及其相关引用环境组合而成的实体(即:闭包=函数+引用环境)

package main

import (
        "fmt"
)

func addNum() func() int{
        var count int =0                                        //计数
        addFun := func () int{                                
                count++
                sumNum := 15+2
                fmt.Println(count,sumNum)              //输出count和sumNum值
                return sumNum
        }
        return addFun
}

func main() {
        sum := addNum()                                 // 不输出
        sum()                                                    // 输出 1 17
        sum()                                                    // 输出 2 17
        addNum()                                             // 不输出
}

 由上面的代码,我们可以看出,addNum() 函数其实不会主动调用addFun()函数,而且在 sum :=addNum() 之后,每次调用 sum() 函数,其实都是调用 addFun() 函数,所以我们可以粗浅的将addNum() 函数当作 addFun 函数的指针,当sum := addNum() 之后,其实可以理解为 将addFun() 传递给了 sum ,当执行 sum() 函数时,其实是执行的 addNum() 函数。

5.有参数的闭包函数

问题描述:下面记录一下有参数调用的闭包函数 

package main

import (
"fmt"
)

func addNum(a int, b int) func(int,int) int{
        var count int =0
        addFun := func (a int, b int) int{
                count++
                sumNum := a+b
                fmt.Println(count,sumNum)
                return sumNum
        }
        return addFun
}

func main() {
        sum := addNum(0, 0)                                 // 不输出
        sum(1, 2)                                                    // 输出 1 3
        sum(2, 3)                                                    // 输出 2 5
        addNum(0, 0)                                             // 不输出
}

 6.defer 函数和方法的延迟调用

问题描述:defer语句的用途是:含有defer语句的函数,会在该函数将要返回之前,调用另一个函数;

package main

import (
"fmt"
)

func printA(a int) {
        fmt.Println("函数一调用", a)                                //输出 函数一调用 5
}
func main() {
        a := 5
        defer printA(a)
        a = 10
        fmt.Println("函数二调用", a)                                //输出 函数二调用 10
}

//使用 defer 延迟调用关键字后,上面程序优先输出 函数二调用,后输出 函数调用一

注意:在for循环和range中,由于 i 和 range 分配的key值 的内存地址不变,所以延迟输出都是取的最后一次循环。如下代码所示

package main

import (
        "fmt"
)

func main() {
        for i := 0;i < 5;i++ {
                fmt.Println(&i,i)
                defer func() { fmt.Println(i) }()
        }
}

 //使用 defer 关键字后,上面程序执行完毕,输出的 i 全为 5, 这是因为在for循环中,所有遍历的i都是用的同一个内存地址

注意:defer 函数或方法后,依旧是在 return 前执行,所以在特定情况下依旧可以修改return返回值。

四、面向对象编程

1. New() 函数

new函数作用于实例化结构体,返回的是实例化后的指针

package main

import (
        "fmt"
)

type Student struct{                                //声明结构体
        name string
        age int
}

func main() {
        stu := new(Student)                        //实例化结构体 Student  ( 这里是指针,同等于:stu := &Student{} )
        stu.name = "王强"                           //结构体属性赋值
        stu.age = 18                                    //结构体属性赋值
        fmt.Println(stu)
        fmt.Println(*stu)
}

 2.结构体的“继承”

Go语言中使用结构体也可以实现其他编程语言中面向对象的继承。

package main

import (
"fmt"
)

type Pepole struct{
        name string
}

func (s *Pepole) Move(){
        fmt.Println(s.name,"向着北边移动中...")
}

type Wangqiang struct{
        leg int8
        *Pepole
}

func (wq *Wangqiang) Step(){
        fmt.Println(wq.name,"迈开",wq.leg,"条腿 ")
}

func main() {
        wq := &Wangqiang{
                leg:2,
                Pepole:&Pepole{
                        name:"王强",
                },
        }
        wq.Step()                                         //王强 迈开 2 条腿
        wq.Move()                                       //王强 向着北边移动中...
}

 五、错误机制

1.error

go没有异常机制,下面接口是通过错误断言判断

func main() {  f, err := os.Open("/test.txt")if err, ok := err.(*os.PathError); ok {fmt.Println("File at path", err.Path, "failed to open")return}fmt.Println(f.Name(), "opened successfully")
}

2.自定义错误 

errors.New可以快速创建错误实例(需要实现error接口)

package errors

// New returns an error that formats as the given text.
func New(text string) error {
        return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
        s string
}

func (e *errorString) Error() string {
        return e.s
}

 3.类似try-catch语法

func Try(fun func(), handler func(interface{})) {
        defer func() {
                if err := recover(); err != nil {
                        handler(err)
                }
        }()
        fun()
}

 

 golang学习笔记-推荐看云-概述 · Go学习笔记 · 看云

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/771817.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android 15兼容性框架变更

在准备支持 Android 15 和以该平台为目标平台时&#xff0c;请将此列表与开发者选项和 ADB 命令结合使用&#xff0c;以测试和调试您的应用。 以下是您可以使用兼容性框架工具进行的操作&#xff1a; 在不实际更改应用的 targetSdkVersion 的情况下测试针对性的变更。您可以使…

【嵌入式——QT】多语言界面

【嵌入式——QT】多语言界面 多语言页面开发步骤tr()函数 多语言页面开发步骤 第一步 在你编写的代码中添加tr()函数&#xff0c;方便之后可以精准的定位到你所需要翻译的部分。 第二步 在.pro文件中添加以下代码&#xff0c;这样会让你生成相应的.ts文件&#xff0c;ts文件是…

深度学习Top10算法之深度神经网络DNN

深度神经网络&#xff08;Deep Neural Networks&#xff0c;DNN&#xff09;是人工神经网络&#xff08;Artificial Neural Networks&#xff0c;ANN&#xff09;的一种扩展。它们通过模仿人脑的工作原理来处理数据和创建模式&#xff0c;广泛应用于图像识别、语音识别、自然语…

安捷伦Agilent 85033E机械校准套件

181/2461/8938产品概述&#xff1a; 网络分析中的测量误差可分为两类:随机误差和系统误差。随机误差和系统误差都是矢量。随机误差是不可重复的测量变化&#xff0c;通常是不可预测的。系统误差是测试设置中可重复的测量变化。 系统误差包括阻抗不匹配、系统频率响应和测试设…

位运算详解教程

位运算的概述 数据以二进制的形式存储在设备中。即0&#xff0c;1两种状态。 &与运算&#xff1a;只有当两位都为1的情况下才为1&#xff0c;其余情况全是0. |或运算&#xff1a;两个位上都为0时&#xff0c;结果才为0 ^异或运算&#xff1a;两个位相同为0.相异为1 ~取…

11、Spring CLI中Action指南

动作指南 这个页面描述了你可以使用的动作: 生成(Generate) generate 动作用于生成文件。它需要一个 to 键来指定目标路径。路径是相对于执行用户定义命令的地方。如果文件已存在,则不会被覆盖。 文件的内容是使用 text 键定义的。 下面的示例展示了一个简单的生成动作…

javaSwing超级玛丽游戏

一、摘要 摘要 近年来&#xff0c;Java作为一种新的编程语言&#xff0c;以其简单性、可移植性和平台无关性等优点&#xff0c;得到了广泛地应用。J2SE称为Java标准版或Java标准平台。J2SE提供了标准的SDK开发平台。利用该平台可以开发Java桌面应用程序和低端的服务器应用程序…

在线测评系统

Hydrooj nodejs版 HustOJ php版 QDUOJ python版 QDUOJ https://gitcode.com/QingdaoU/OnlineJudge/tree/master HustOJ hustoj: hustoj -- 流行的OJ系统&#xff0c;跨平台、易安装、有题库 Hydrooj https://hydro.js.org/docs/

人工智能聊天机器人与大型语言模型 (LLM):哪个适合您的业务?

简介&#xff1a;欢迎来到未来 您可能听说过人工智能聊天机器人和大型语言模型 (LLM)&#xff0c;对吧&#xff1f; 这些技术奇迹正在重塑企业的沟通和运营方式。 但是&#xff0c;这是一个价值百万美元的问题&#xff1a;哪一个适合您的业务&#xff1f; 让我们深入了解一下&…

【C++航海王:追寻罗杰的编程之路】queue

目录 1 -> queue的介绍和使用 1.1 -> queue的介绍 1.2 -> queue的使用 1.3 -> queue的模拟实现 1 -> queue的介绍和使用 1.1 -> queue的介绍 queue的文档介绍 1. 队列是一种容器适配器&#xff0c;专门用于在FIFO(先进先出)上下文中操作&#xff0c;其…

【C++】每日一题 137 只出现一次的数字

给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。 你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 #include <vector>int singleNumber(std::vecto…

力扣刷题31-33(力扣 0024/0070/0053)

今日题目&#xff1a; 24. 两两交换链表中的节点 题目&#xff1a;给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0c;只能进行节点交换&#xff09; 思路&…

Unity DOTS系列之托管/非托管Component的区别与性能分析

最近DOTS发布了正式的版本, 我们来分享一下DOTS里面托管与非托管Component的区别与性能分析&#xff0c;方便大家上手学习掌握Unity DOTS开发。托管与非托管的区别在于是不是基于自动垃圾回收的。托管是由垃圾回收器来负责自动回收&#xff0c;非托管需要我们手动来做相关内存管…

Linux离线安装Docker-Oracle_11g

拉取oracle11g镜像 docker pull registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g创建11g容器 docker run -d -p 1521:1521 --name oracle11g registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g查看容器是否创建成功 docker ps -a导出oracle容器&#xff0c;查看…

深入探索MySQL高阶查询语句的艺术与实践

目录 引言 一、条件查询 &#xff08;一&#xff09;比较运算符查询 1.使用匹配符号查询 2.范围查找 &#xff08;二&#xff09;逻辑运算符 二、关键字排序 三、分组与聚合函数 四、限制查询 五、别名 &#xff08;一&#xff09;设置列别名 &#xff08;二&#x…

从零学算法212

212.给定一个 m x n 二维字符网格 board 和一个单词&#xff08;字符串&#xff09;列表 words&#xff0c; 返回所有二维网格上的单词 。 单词必须按照字母顺序&#xff0c;通过 相邻的单元格 内的字母构成&#xff0c;其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同…

@JsonProperty作用

jackson的maven依赖 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.5.3</version> </dependency>JsonProperty 此注解用于属性上&#xff0c;作用是把该属…

二叉树|530.二叉搜索树的最小绝对差

力扣题目链接 class Solution { private: vector<int> vec; void traversal(TreeNode* root) {if (root NULL) return;traversal(root->left);vec.push_back(root->val); // 将二叉搜索树转换为有序数组traversal(root->right); } public:int getMinimumDiffe…

Mac vue3 使用可选链操作符 ?. 及空值合并操作符 ??编译报错

项目场景&#xff1a; uniapp使用vue3开发&#xff0c;引入uview-plus版本&#xff0c;无法编译通过&#xff08;无法使用可选链操作符 ?. &#xff09; 开发环境&#xff1a; 产品分类&#xff1a; uniapp/App P…

YoloV5改进策略:Block改进|ECA-Net:用于深度卷积神经网络的高效通道注意力|ECA+压缩膨胀Block实现涨点(独家原创)

摘要 本文使用ECA-Net注意力机制配合压缩膨胀的Block实现涨点。涨点方法是我自己独创的&#xff0c;改进方法简单易用&#xff0c;方便大家用于论文的改进。 论文&#xff1a;《ECA-Net&#xff1a;用于深度卷积神经网络的高效通道注意力》 arxiv.org/pdf/1910.03151.pdf 最…