Go 语言面试题(一):基础语法

news2024/11/13 7:58:08

文章目录

    • Q1 = 和 := 的区别?
    • Q2 指针的作用?
    • Q3 Go 允许多个返回值吗?
    • Q4 Go 有异常类型吗?
    • Q5 什么是协程(Goroutine)
    • Q6 如何高效地拼接字符串
    • Q7 什么是 rune 类型
    • Q8 如何判断 map 中是否包含某个 key ?
    • Q9 Go 支持默认参数或可选参数吗?
    • Q10 defer 的执行顺序
    • Q11 如何交换 2 个变量的值?
    • Q12 Go 语言 tag 的用处?
    • Q13 如何判断 2 个字符串切片(slice) 是相等的?
    • Q14 字符串打印时,%v 和 %+v 的区别
    • Q15 Go 语言中如何表示枚举值(enums)
    • Q16 空 struct{} 的用途

Q1 = 和 := 的区别?

:= 声明+赋值

= 仅赋值

var foo int
foo = 10
// 等价于
foo := 10

Q2 指针的作用?

指针用来保存变量的地址。

例如

var x =  5
var p *int = &x
fmt.Printf("x = %d",  *p) // x 可以用 *p 访问
  • 运算符,也称为解引用运算符,用于访问地址中的值。
    &运算符,也称为地址运算符,用于返回变量的地址。

Q3 Go 允许多个返回值吗?

允许

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

func main() {
   a, b := swap("A", "B")
   fmt.Println(a, b) // B A
}

Q4 Go 有异常类型吗?

Go 没有异常类型,只有错误类型(Error),通常使用返回值来表示异常状态。

f, err := os.Open("test.txt")
if err != nil {
    log.Fatal(err)
}

Q5 什么是协程(Goroutine)

Goroutine 是与其他函数或方法同时运行的函数或方法。 Goroutines 可以被认为是轻量级的线程。 与线程相比,创建 Goroutine 的开销很小。 Go应用程序同时运行数千个 Goroutine 是非常常见的做法。

Q6 如何高效地拼接字符串

Go 语言中,字符串是只读的,也就意味着每次修改操作都会创建一个新的字符串。如果需要拼接多次,应使用 strings.Builder,最小化内存拷贝次数。

var str strings.Builder
for i := 0; i < 1000; i++ {
    str.WriteString("a")
}
fmt.Println(str.String())

Q7 什么是 rune 类型

ASCII 码只需要 7 bit 就可以完整地表示,但只能表示英文字母在内的128个字符,为了表示世界上大部分的文字系统,发明了 Unicode, 它是ASCII的超集,包含世界上书写系统中存在的所有字符,并为每个代码分配一个标准编号(称为Unicode CodePoint),在 Go 语言中称之为 rune,是 int32 类型的别名。

Go 语言中,字符串的底层表示是 byte (8 bit) 序列,而非 rune (32 bit) 序列。例如下面的例子中 语 和 言 使用 UTF-8 编码后各占 3 个 byte,因此 len(“Go语言”) 等于 8,当然我们也可以将字符串转换为 rune 序列。

fmt.Println(len("Go语言")) // 8
fmt.Println(len([]rune("Go语言"))) // 4

Q8 如何判断 map 中是否包含某个 key ?

if val, ok := dict["foo"]; ok {
    //do something here
}

dict[“foo”] 有 2 个返回值,val 和 ok,如果 ok 等于 true,则说明 dict 包含 key “foo”,val 将被赋予 “foo” 对应的值。
在这里插入图片描述

Q9 Go 支持默认参数或可选参数吗?

Go 语言不支持可选参数(python 支持),也不支持方法重载(java支持)。

Q10 defer 的执行顺序

多个 defer 语句,遵从后进先出(Last In First Out,LIFO)的原则,最后声明的 defer 语句,最先得到执行。
defer 在 return 语句之后执行,但在函数退出之前,defer 可以修改返回值。
例如:

func test() int {
	i := 0
	defer func() {
		fmt.Println("defer1")
	}()
	defer func() {
		i += 1
		fmt.Println("defer2")
	}()
	return i
}

func main() {
	fmt.Println("return", test())
}
// defer2
// defer1
// return 0

这个例子中,可以看到 defer 的执行顺序:后进先出。但是返回值并没有被修改,这是由于 Go 的返回机制决定的,执行 return 语句后,Go 会创建一个临时变量保存返回值,因此,defer 语句修改了局部变量 i,并没有修改返回值。那如果是有名的返回值呢?

func test() (i int) {
	i = 0
	defer func() {
		i += 1
		fmt.Println("defer2")
	}()
	return i
}

func main() {
	fmt.Println("return", test())
}
// defer2
// return 1

这个例子中,返回值被修改了。对于有名返回值的函数,执行 return 语句时,并不会再创建临时变量保存,因此,defer 语句修改了 i,即对返回值产生了影响。

Q11 如何交换 2 个变量的值?

a, b := "A", "B"
a, b = b, a
fmt.Println(a, b) // B A

Q12 Go 语言 tag 的用处?

tag 可以理解为 struct 字段的注解,可以用来定义字段的一个或多个属性。框架/工具可以通过反射获取到某个字段定义的属性,采取相应的处理方式。tag 丰富了代码的语义,增强了灵活性。

例如:

package main

import "fmt"
import "encoding/json"

type Stu struct {
	Name string `json:"stu_name"`
	ID   string `json:"stu_id"`
	Age  int    `json:"-"`
}

func main() {
	buf, _ := json.Marshal(Stu{"Tom", "t001", 18})
	fmt.Printf("%s\n", buf)
}

这个例子使用 tag 定义了结构体字段与 json 字段的转换关系,Name -> stu_name, ID -> stu_id,忽略 Age 字段。很方便地实现了 Go 结构体与不同规范的 json 文本之间的转换。

Q13 如何判断 2 个字符串切片(slice) 是相等的?

go 语言中可以使用反射 reflect.DeepEqual(a, b) 判断 a、b 两个切片是否相等,但是通常不推荐这么做,使用反射非常影响性能。

通常采用的方式如下,遍历比较切片中的每一个元素(注意处理越界的情况)。

func StringSliceEqualBCE(a, b []string) bool {
    if len(a) != len(b) {
        return false
    }

    if (a == nil) != (b == nil) {
        return false
    }

    b = b[:len(a)]
    for i, v := range a {
        if v != b[i] {
            return false
        }
    }

    return true
}

Q14 字符串打印时,%v 和 %+v 的区别

%v 和 %+v 都可以用来打印 struct 的值,区别在于 %v 仅打印各个字段的值,%+v 还会打印各个字段的名称。

type Stu struct {
	Name string
}

func main() {
	fmt.Printf("%v\n", Stu{"Tom"}) // {Tom}
	fmt.Printf("%+v\n", Stu{"Tom"}) // {Name:Tom}
}

但如果结构体定义了 String() 方法,%v 和 %+v 都会调用 String() 覆盖默认值。

Q15 Go 语言中如何表示枚举值(enums)

通常使用常量(const) 来表示枚举值。

type StuType int32

const (
	Type1 StuType = iota
	Type2
	Type3
	Type4
)

func main() {
	fmt.Println(Type1, Type2, Type3, Type4) // 0, 1, 2, 3
}

参考 What is an idiomatic way of representing enums in Go? - StackOverflow

Q16 空 struct{} 的用途

使用空结构体 struct{} 可以节省内存,一般作为占位符使用,表明这里并不需要一个值。

fmt.Println(unsafe.Sizeof(struct{}{})) // 0

比如使用 map 表示集合时,只关注 key,value 可以使用 struct{} 作为占位符。如果使用其他类型作为占位符,例如 int,bool,不仅浪费了内存,而且容易引起歧义。

type Set map[string]struct{}

func main() {
	set := make(Set)

	for _, item := range []string{"A", "A", "B", "C"} {
		set[item] = struct{}{}
	}
	fmt.Println(len(set)) // 3
	if _, ok := set["A"]; ok {
		fmt.Println("A exists") // A exists
	}
}

再比如,使用信道(channel)控制并发时,我们只是需要一个信号,但并不需要传递值,这个时候,也可以使用 struct{} 代替。

func main() {
	ch := make(chan struct{}, 1)
	go func() {
		<-ch
		// do something
	}()
	ch <- struct{}{}
	// ...
}

再比如,声明只包含方法的结构体。

type Lamp struct{}

func (l Lamp) On() {
        println("On")

}
func (l Lamp) Off() {
        println("Off")
}

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

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

相关文章

STM32--GPIO

文章目录 GPIO简介GPIO的基本结构GPIO位结构GPIO模式LED和蜂鸣器LED闪烁工程及程序原码代码&#xff1a; 蜂鸣器工程和程序原码代码 传感器光敏传感器控制蜂鸣器工程代码 GPIO简介 GPIO&#xff08;General Purpose Input Output&#xff09;是通用输入/输出口的简称。它是一种…

利用el-button 画圆 ,通过border-radius >50% 就成圆形

<el-button type"danger" style"border-radius: 100%; height: 100px;width: 100px;" plain><span style"font-weight: bold;">工艺分析</span></el-button>通过border-radius >50% 就成圆形。 border-radius: 50% …

STM32基础入门学习笔记:面包板 配件包扩展模块与编程

文章目录&#xff1a; 一&#xff1a;阵列键盘 1.阵列键盘测试程序 KEYPAD4x4.h KEYPAD4x4.c main.c 2.键盘中断测试程序 NVIC.h NVIC.c main.c 二&#xff1a;舵机控制 1.延时函数驱动舵机程序 SG90.h SG90.c main.c 2.PWM(脉冲宽度调制 脉宽调制/占空比)驱动…

极海APM32F003F6P6烧写问题解决记录

工作中遇到的&#xff0c;折腾了好久&#xff0c;因为电脑重装过一遍系统&#xff0c;软件也都重新安装了&#xff0c;所以不知道之前的配置是什么&#xff0c;旧项目代码编译没问题&#xff0c;烧写时疯狂报错&#xff0c;用的是JLink。 keil版本v5.14 win10版本 JLink版本…

PHP8的表达式-PHP8知识详解

表达式是 PHP 最重要的基石。在 PHP8中&#xff0c;几乎所写的任何东西都是一个表达式。简单但却最精确的定义一个表达式的方式就是"任何有值的东西"。 最基本的表达式形式是常量和变量。当键入"$a 5"&#xff0c;即将值"5"分配给变量 $a。&quo…

RocketMQ Learning

一、RocketMQ RocketMQ的产品发展 MetaQ&#xff1a;2011年&#xff0c;阿里基于Kafka的设计使用Java完全重写并推出了MetaQ 1.0版本 。 2012年&#xff0c;阿里对MetaQ的存储进行了改进&#xff0c;推出MetaQ 2.0&#xff0c;同年阿里把Meta2.0从阿里内部开源出来&am…

【Rust】Rust学习 第四章认识所有权

第四章认识所有权 所有权&#xff08;系统&#xff09;是 Rust 最为与众不同的特性&#xff0c;它让 Rust 无需垃圾回收&#xff08;garbage collector&#xff09;即可保障内存安全。因此&#xff0c;理解 Rust 中所有权如何工作是十分重要的。 4.1 所有权 所有运行的程序都…

行业报告 | 大模型助力产业,持续推进人工智能科技创新

原创 | 文 BFT机器人 随着AI应用深入千行百业&#xff0c;大模型在多个产业领域发挥着积极的作用。英伟达、META、微软等多家公司纷纷宣布AI相关行业的合作和并购机会&#xff0c;加速研发各垂类领域AI大模型&#xff0c;算力需求有望持续向上。 英伟达&#xff1a;宣布5000万…

[oeasy]python0081_[趣味拓展]ESC键进化历史_键盘演化过程_ANSI_控制序列_转义序列_CSI

光标位置 回忆上次内容 上次了解了 新的转义模式 \033 逃逸控制字符 escape 这个字符 让字符串 退出标准输出流进行控制信息的设置 可以设置 光标输出的位置 ASR33中的ALT MODE 是 今天的ESC键吗&#xff1f;&#xff1f;&#xff1f;&#xff1f;&#x1f914; 查询文档…

2023-08-06 LeetCode每日一题(24. 两两交换链表中的节点)

2023-08-06每日一题 一、题目编号 24. 两两交换链表中的节点二、题目链接 点击跳转到题目位置 三、题目描述 给你一个链表&#xff0c;两两交换其中相邻的节点&#xff0c;并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题&#xff08;即&#xff0…

MySQL索引原理以及SQL优化

文章目录 一、索引1.1 索引分类1.1.1 按数据结构分类1.1.2 按物理存储分类1.1.3 按列属性分类1.1.4 按列的个数索引 1.2 索引的代价1.3 索引的使用场景1.4 不使用索引的场景 二、索引的实现原理2.1 索引存储2.2 页2.3 InnoDB中的B树2.4 InnoDB的体系结构2.5 最左匹配原则2.6 覆…

人工智能自然语言处理:抽取式文本分割(Text Segmentation)算法介绍总结,智能断句解决文本过长问题

NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型压缩算法等 专栏详细介绍:NLP专栏简介:数据增强、智能标注、意图识别算法|多分类算法、文本信息抽取、多模态信息抽取、可解释性分析、性能调优、模型…

快速修复应用程序中的问题的利器—— Android热修复

热修复技术在Android开发中扮演着重要的角色&#xff0c;它可以帮助开发者在不需要重新发布应用程序的情况下修复已经上线的应用程序中的bug或者添加新的功能。 一、热修复是什么&#xff1f; 热修复&#xff08;HotFix&#xff09;是一种在运行时修复应用程序中的问题的技术…

2023/08/05【网络课程总结】

1. 查看git拉取记录 git reflog --dateiso|grep pull2. TCP/IP和OSI七层参考模型 3. DNS域名解析 4. 预检请求OPTIONS 5. 渲染进程的回流(reflow)和重绘(repaint) 6. V8解析JavaScript 7. CDN负载均衡的简单理解 8. 重学Ajax 重学Ajax满神 9. 对于XML的理解 大白话叙述XML是…

图像 检测 - RetinaNet: Focal Loss for Dense Object Detection (arXiv 2018)

图像 检测 - RetinaNet: Focal Loss for Dense Object Detection - 密集目标检测中的焦点损失&#xff08;arXiv 2018&#xff09; 摘要1. 引言2. 相关工作References 声明&#xff1a;此翻译仅为个人学习记录 文章信息 标题&#xff1a;RetinaNet: Focal Loss for Dense Obje…

Matlab进阶绘图第25期—三维密度散点图

三维密度散点图本质上是一种特征渲染的三维散点图&#xff0c;其颜色表示某一点所在区域的密度信息。 除了作图&#xff0c;三维密度散点图绘制的关键还在于密度的计算。 当然&#xff0c;不管是作图还是密度的计算&#xff0c;这些在《Matlab论文插图绘制模板》和《Matlab点…

小研究 - 基于 MySQL 数据库的数据安全应用设计(二)

信息系统工程领域对数据安全的要求比较高&#xff0c;MySQL 数据库管理系统普遍应用于各种信息系统应用软件的开发之中&#xff0c;而角色与权限设计不仅关乎数据库中数据保密性的性能高低&#xff0c;也关系到用户使用数据库的最低要求。在对数据库的安全性进行设计时&#xf…

学习笔记-JAVAJVM-JVM的基本结构及概念

申明&#xff1a;文章内容是本人学习极客时间课程所写&#xff0c;文字和图片基本来源于课程资料&#xff0c;在某些地方会插入一点自己的理解&#xff0c;未用于商业用途&#xff0c;侵删。 原资料地址&#xff1a;课程资料 什么是JVM 原文连接&#xff1a; 原文连接 JVM是J…

即将发布的 Kibana 版本可运行 Node.js 18

作者&#xff1a;Thomas Watson Kibana 构建在 Node.js 框架之上。 为了确保每个 Kibana 版本的稳定性和使用寿命&#xff0c;我们始终将捆绑的 Node.js 二进制文件保持为最新的最新长期支持 (LTS) 版本。 当 Node.js 版本 18 升级到 LTS 时&#xff0c;我们开始将 Kibana 升级…

【WebRTC---源码篇】(二十三)JitterBuffer

PacketBuffer packetbuffer类中重要的一些变量 // buffer_.size() and max_size_ must always be a power of two.const size_t max_size_;//能存储的最大元素个数// The fist sequence number currently in the buffer.uint16_t first_seq_num_ RTC_GUARDED_BY(crit_);//这个…