go语言语法基础

news2024/11/27 7:44:42

文章目录

  • 前言
  • 一、输入和输出
    • 常用的字符串格式化符号
  • 二、注释
  • 三、Go常用基本语言数据类型
    • 数字类型
    • 布尔类型
    • 字符类型
    • 变量与常量
    • 数组和切片
      • 数组
      • 切片
    • map类型
      • 创建map
      • 特别提醒
    • 指针
  • 四、运算符
  • 五、条件判断语句
    • if系列
    • switch
    • 六、循环语句
      • for循环标准写法
      • 死循环
      • while循环
      • do while
      • 类似python的for循环
      • 特别说明
  • 七、break和continue
  • 八、函数
    • 无参数无返回值
    • 有参数无返回值
    • 有多个参数的函数
    • 不定长参数的函数
    • 没有返回值的函数
    • 有返回值的函数
    • 有多个返回值的函数(注意)
    • 在返回值里定义变量(注意)
    • 闭包函数(匿名函数)
    • 将函数作为参数进行传递(注意)
    • 值传递与引用传递
    • 变量作用域
      • 特别说明
  • 九、类型转换
    • 数字之间转换
    • 字符型与数字类型之间的转换
      • 将string-->int
      • 将int-->string
      • 将string-->float
      • 将float-->string
  • 总结


前言

考完研了,最近在学校安排的培训机构实习(懂得都懂),培训机构有几个方向,我选了go语言后端(本人java很烂,尚硅谷200个小时的视频我是真看不下去),本文记录一下go语言的语法基础。
还有就是,本博文的学习资料来源是菜鸟教程和枫枫知道的博文,后面会附上链接。
他们就相当于字典,面面俱到,本博文就相当于笔记,写一些注意事项,适合有其他语言基础的快速熟悉go语言,我主要是写一些需要注意的地方,这是我与他们不一样的地方
菜鸟教程-go语言

枫枫知道博客

枫枫知道B站go语言教程


一、输入和输出

换行输出

fmt.Println()

格式化输出

fmt.Printf()

常用的字符串格式化符号

%v 按值的本来值输出
%#v 输出GO语言语法格式的值
%T 输出GO语言语法格式的类型和值
%b 整型以二进制方式显示
%o 整型以八进制方式显示
%d 整型以十进制方式显示
%x 整型以十六进制方式显示
%X 整型以十六进制、字母大写方式显示
%f 浮点数
%p 指针,十六进制方式显示
%c 该值对应的unicode码值

输入

var a int//首先定义一个变量
fmt.Scan(&a)//然后写输入函数,记得带指针

二、注释

单行注释
//
多行注释
/*
*/

三、Go常用基本语言数据类型

数字类型

数字类型分为整型和浮点型,这个在其他语言里面也有,不再说了。
这里只想强调几点

1.我上面写的所有数据类型,请分别看成是一种数据类型,就是int是int,int8是int8,他们不是等价的
在这里插入图片描述
2.没有特殊需求,整数用int其实就行了。
3.uint是无符号整数,具体什么是无符号整数,百度或gpt吧,要是详细说都能写篇写小作文了。

布尔类型

其他语言也有布尔类型,这里依然只想强调1点

在go语言,1不能代表true,0不能代表false
在这里插入图片描述
在这里插入图片描述

字符类型

go语言里面跟很多语言也是一样的,分为byte和string类型,
在这个基础上,go语言还有个rune类型。
然后就是强调环节
go语言不像python,对于byte类型和string类型区别不明显。

在go语言里面,byte必须用 ‘’,也就是单引号给引起来
string类型使用双引号给引起来,如果需要输入很多文字,使用反单引号给引起来,也就是1左边的那个符号

var a byte = 'a'
	fmt.Printf("%c %d\n", a, a)
	var a1 uint8 = 97
	fmt.Printf("%c %d\n", a1, a1)

go语言里面的源码
在这里插入图片描述
rune这种数据类型跟byte的作用差不多,用来转换对应的码

var z rune = '中'
fmt.Printf("%c %d\n", z, z)

还有就是默认值问题,在go语言里面,如果你声明了一个变量,但是没有赋值,那么这个变量的值就是对应变量的零值
int就是0, bool就是false,字符串就是""

	var n string
	var age int
	var sex bool
	fmt.Printf("%#v\n", n)
	fmt.Printf("%#v\n", age)
	fmt.Printf("%#v\n", sex)

变量与常量

这里想说的是,
常量使用const来声明,必须在声明的时候就初始化,且一但初始化后就不能修改。

还有就是变量的声明,go语言的类型是在写后面,如果你之前写过java,刚开始应该是不太适应,写多了慢慢就适应了。

变量的声明有多种写法,选一个你喜欢的写就行了。这里也会写一些几种变量的声明。

//指定变量的类型
var a string = "hello world"
var b int = 1
var c, d int = 1, 2
//自行推断类型
var a = 1
a := 50 

//先声明变量,后初始化
var a int
a = 1

注:后面的数组,切片,map等还可以使用make初始化

数组和切片

数组

数组类型就很像java里面的静态数组,确定大小后就不能改了,
想要扩大就要写代码来扩大数组,限制比较多。然后这个数组类型也支持索引,但是不支持逆向索引(就是从后面往前面数是,-1,-2,-3,…),下面写一个代码就行了

还有就是要注意边界值!!!

var nameList [3]string = [3]string{"ss", "aa", "bb"}
	fmt.Println(nameList)
	//索引,go语言没有逆向索引
	fmt.Println(nameList[0])
	fmt.Println(nameList[2])
	fmt.Println(nameList[len(nameList)-1])

这里想说的就是,go语言里面初始化数据类型的方式比较多,选一个自己喜欢的写法就行了。

切片

切片类型(Slice)就很像python里面的list,也就是动态数组
关于切片需要注意两个问题
1.长度和容量问题
在go语言里面长度指的是这个切片里面有多少个元素,容量是指底层里面可以装多少个元素。
我个人理解是,就相当于水杯,长度就是水杯里面有多少水,容量就是,这个杯子最大可以装多少水。
然后就是,切片类型当然支持自动扩容。

2.引用问题
切片是引用类型,切片是引用类型,多个切片可以引用同一个底层数组。修改一个切片的元素可能会影响其他引用了同一底层数组的切片。

关于切片就说这么多,这个需要多练,才能掌握。

map类型

map类型就是python里面的字典

创建map

这里还是要说一下,创建map依然有好几个写法,选一个自己喜欢的写就行了

var usermap  = map[int]string{
		1: "枫枫",
		2: "张三",
		4: "",
	}
	fmt.Println(usermap)

fmt.Println(usermap)
	//增加
	usermap[5] = "你好"
	fmt.Println(usermap)

在这里插入图片描述

delete(usermap, 4)
	fmt.Println(usermap)

在这里插入图片描述

	usermap[1] = "枫枫知道"
	fmt.Println(usermap)

在这里插入图片描述

fmt.Println(usermap[1])

在这里插入图片描述

特别提醒

map必须初始化才能使用

	var amap map[string]string
	amap["name"] = "枫枫"
	fmt.Println(amap)

在这里插入图片描述

指针

我是觉得跟c语言里面的指针是一模一样,请看下面这段代码

var ip *int       

var a int
fmt.Scan(&a)

func deliver2(num *int) int {
	*num += 1
	return *num
}

跟c语言是不是一模一样

四、运算符

关于运算符,go语言里面该有的都有,这里依然只强调几点

1.go语言里面只有右++,没有左++,减减也是一样的(说说实话,我是觉得左右加加减减是不利于代码维护以及阅读,这样只有一个反而好一点,就那个左右加加减减的面试题,现在让我做我也不一定做的对)

2.记不住优先级就加括号
在这里插入图片描述
在这里插入图片描述

五、条件判断语句

这里只想写个写法,跟其他有没有除了写法没有其他区别

if系列

如果你学过其他语言,稍微看一下就行了


if 布尔表达式 {//是的,条件这里没有括号
   /* 在布尔表达式为 true 时执行 */
}

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

//中断式 谓语句

	if age <= 0 {
		fmt.Println("未出生")
		return
	}
	if age <= 18 {
		fmt.Println("未成年")
		return
	}
	if age <= 35 {
		fmt.Println("青少年")
		return
	}
	fmt.Println("中年")
//嵌入式写法
	if age <= 18 {
		if age <= 0 {
			fmt.Println("未出生")
		} else {
			fmt.Println("未成年")
		}
	} else {
		if age <= 35 {

			fmt.Println("青年")
		} else {
			fmt.Println("中年")
		}
	}

switch

这里要注意
1.go语言里面的switch case 默认case后面自带break(是的,不会出现java里面没写break,然后执行到其他case的情况)

2.go语言里面的case可以写判断条件(我记得java里面就是只能写个数字)
下面两段代码,看一下就行了

func main() {
  fmt.Println("请输入你的年龄:")
  var age int
  fmt.Scan(&age)

  switch {
  case age <= 0:
    fmt.Println("未出生")
  case age <= 18:
    fmt.Println("未成年")
  case age <= 35:
    fmt.Println("青年")
  default:
    fmt.Println("中年")
  }
}
func main() {
  fmt.Println("请输入星期数字:")
  var week int
  fmt.Scan(&week)

  switch week {
  case 1:
    fmt.Println("周一")
  case 2:
    fmt.Println("周二")
  case 3:
    fmt.Println("周三")
  case 4:
    fmt.Println("周四")
  case 5:
    fmt.Println("周五")
  case 6, 7:
    fmt.Println("周末")
  default:
    fmt.Println("错误")
  }
}

六、循环语句

go语言里面的循环语句只有for语句,没有while语句。

go语言的理念里,认为for循环也可以实现while循环,所以就没有while循环

还有就是go语言里面也没有do while语句,但是也可以使用for循环来实现。

下面就是代码

for循环标准写法

//求100以内的和
//跟java,c是不是很像
//但我不知道为什么go语言不喜欢写括号
sum := 0
	for i := 0; i <= 100; i++ {
		fmt.Println(i)
		sum += i
	}
	fmt.Println(sum)

死循环

	//死循环
	for i := 0; true; i++ {}

	//这样写死循环也是可以的
	for true{}

	for {}

while循环

//go语言没有while循环,下面是go语言里面的while模式
	var sum int
	var i int = 1
	for i <= 100 {
		sum += i
		i++
	}
	fmt.Println(sum)

do while

	//do while 模式
	sum := 0
	var i int = 1
	for {
		sum += i
		i++
		if i == 101 {
			break
		}
	}
	fmt.Println(sum)

类似python的for循环

//类似python一样的for循环
	var list = []string{"枫枫", "知道"}
	for index, item := range list {
		fmt.Println(index, item)
	}

特别说明

go语言认为变量定义了就要使用,不然就会报错,你不使用这个变量就不要定义。但是我们必须要接收两个变量该怎么办呢?
可以使用下划线来代替这个变量,这个在go语言里面就可以理解为占位用的。比如下面这段代码

var list = []string{"枫枫", "知道"}
	for _, item := range list {
		fmt.Println(index, item)
	}

在这段代码中,假如我不需要index,就可以写成下划线。

七、break和continue

跟其他语言里面的作用是一模一样,没有要补充的

八、函数

go语言里面的函数,我愿称之为抽象,在这里插入图片描述我是真没见过如此抽象的东西,我都不知道这里能不能写清楚。

我在之前说go语言里面 if 和 for 循环不知道为什么不喜欢写括号,现在你会函数里面疯狂写括号在这里插入图片描述
先来简单一点

无参数无返回值

func sayHello() {
	fmt.Println("hello")
}

有参数无返回值

func param1(id string) {
	fmt.Println(id)
}

有多个参数的函数

func param2(id string, userName string) {
	fmt.Println(id, userName)
}

// 当多个参数的数据类型相同的时候,写一个就行了
func param3(id, userName string) {
	fmt.Println(id, userName)
}

不定长参数的函数

类比python里面的不定长参数

// 没有确定长度的参数
func add(numerList ...int) {
	var sum int
	for _, i2 := range numerList {
		sum += i2
	}
	fmt.Println(sum)
}

没有返回值的函数

// 没有返回值的函数
func r1() {
	// 没有返回值
	return
}

有返回值的函数

func r2() bool {
	return false
}

有多个返回值的函数(注意)

友友们,注意了,第一个括号来了,如果你想返回多个值,要加个括号。这里算是go语言的特性,我记得java基础里面函数是只能返回一个数据,python里面,虽然return可以返回多个变量,但是python会自动给你转成tuple类型,但是这里就真的是多个变量,你接收的时候也需要多个变量

// 有多个返回值的函数
func r3() (string, bool) {
	return "", false
}
func main() {

	a, b := r3()
	fmt.Printf("%#v,%#v", a, b)
	}

在返回值里定义变量(注意)

友友们还记得上面我们说的默认值吗?这里可以说是go语言的特性。
在返回值里定义了参数,然后直接写个return就会默认返回定义在返回值里面的数,我们也可以对返回值里的变量进行修改,那么,最后返回的时候,就是我们修改过的返回的变量。

func r4() (val string, ok bool) {
	if true {
		val = "12"
		return
	}
	return
}

func main() {

	a, b := r4()
	fmt.Printf("%#v,%#v", a, b)
	}

闭包函数(匿名函数)

 // 定义一个匿名函数并将其赋值给变量add
    add := func(a, b int) int {
        return a + b
    }
     // 调用匿名函数
    result := add(3, 5)
    fmt.Println("3 + 5 =", result)

将函数作为参数进行传递(注意)

go语言里面还可以将函数作为参数来进行传递。
注意,go语言里面不能写函数嵌套,但是我们可以将函数作为参数进行传递,来实现嵌套(其实还是匿名函数)

func awaitAdd(awaitSecond int) func(...int) int {
	return func(numberList ...int) (sum int) {
		for _, i2 := range numberList {
			sum += i2
		}
		return sum
	}
}

func getSequence() func() int {
   i:=0
   return func() int {
      i+=1
     return i  
   }
}

值传递与引用传递

一句话就是,值传递相当于传递了变量的副本,函数内部是对变量的副本进行修改,不会对变量本身产生任何影响,引用传递就是把变量的指针给传递过去,这样函数内部的任何变化也会引起外部变量的修改。写法跟c语言是一模一样

package main

import "fmt"


func deliver(num int) int {
	num += 1
	return num
}

func deliver2(num *int) int {
	*num += 1
	return *num
}

func main() {
	num := 1
	fmt.Println("没有传递给deliver之前的值:", num)
	fmt.Println("经过deliver之后的值", deliver(num))
	fmt.Println("外面的值", num)

	//&是取地址,*是解引用,去这个地址指向的值
	fmt.Println("没有传递给deliver2之前的值:", num)
	fmt.Println("经过deliver之后的值", deliver2(&num))
	fmt.Println("外面的值", num)

}

变量作用域

看代码吧,简单说就是定义在任何函数之外的变量。

package main
//全局变量
var a int = 1
func main() {
//局部变量和
var b int = 1
}

特别说明

在全局变量里面,使用const定义的常量 ,大写开头可以被其他go语言文件访问到,但是小写开头不行。

package version

const Version = "1.1.1.1"

九、类型转换

说明一下,go语言不支持隐式转换类型,必须要写怎么转

数字之间转换

var a int = 10
var b float64 = float64(a)

字符型与数字类型之间的转换

将string–>int

var str string = "10"
var num int
num, _ = strconv.Atoi(str)

将int–>string

 num := 123
    str := strconv.Itoa(num)
    fmt.Printf("整数 %d  转换为字符串为:'%s'\n", num, str)

将string–>float

  str := "3.14"
    num, err := strconv.ParseFloat(str, 64)
    if err != nil {
        fmt.Println("转换错误:", err)
    } else {
        fmt.Printf("字符串 '%s' 转为浮点型为:%f\n", str, num)
    }

将float–>string

 num := 3.14
    str := strconv.FormatFloat(num, 'f', 2, 64)
    fmt.Printf("浮点数 %f 转为字符串为:'%s'\n", num, str)

总结

到这里,go语言基础部分讲的差不多了,剩下的就是go语言的类似面向对象的东西(结构体,接口),异常处理,I/O操作,反射,泛型,协程,channel(特性)等东西了。后面我还会再写,今天再放在一起就太多了。然后,有什么问题可以提出来,博主看到后会马上修改。谢谢。
记得点个赞和收藏

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

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

相关文章

java设计模式学习之【观察者模式】

文章目录 引言观察者模式简介定义与用途实现方式 使用场景优势与劣势在Spring框架中的应用观察者示例代码地址 引言 想象你在一个在线拍卖会上竞标一件珍贵的艺术品。每当有人出价更高&#xff0c;系统都会立即通知你。这个实时更新机制使你可以做出快速反应。这种模式&#x…

Linux之进程管理

什么是进程 在linux中每个执行的程序都称为一个进程&#xff0c;每个进程都分配一个ID号&#xff08;pid进程号&#xff09;。每个进程都可能以两种方式存在&#xff0c;即前台和后天。前台进程就是用户目前的屏幕上可以进行操作的。后台进程则是实际在操作&#xff0c;但屏幕…

hugo-theme-kiwi V0.0.2 博客主题上新了时间轴

至此佳节&#xff0c;我在此给正在屏幕前浏览本文的您和您的家人&#xff0c;恭祝元旦快乐&#xff0c;虽然&#xff0c;这声祝福是晚了&#xff0c;但却不妨碍我我由内心深处对您和您的家人的诚挚祝福&#xff01; 新的一年&#xff0c;从这一天逐渐步入我们的生活&#xff0c…

web等保评测需要实机查看的操作系统、服务器、数据库和应用部分

“等保测评”全称是信息安全等级保护测评。是经公安部认证的具有资质的测评机构&#xff0c;依据国家信息安全等级保护规范规定&#xff0c;受有关单位委托&#xff0c;按照有关管理规范和技术标准&#xff0c;对信息系统安全等级保护状况进行检测评估的活动。 本文陆续将遇到的…

『番外篇九』SwiftUI 实战:打造一款“五脏俱全”的网络图片显示 App(上)

概览 俗话说得好:“读书破万卷,下笔如有神”。不过如果把这句话放到编程的学习上可就不那么贴切了。 要想熟练掌握一门编程语言,光看书是绝对不够的。我们还需尽可能的多撸码、早撸码,撸到无路可退、海枯石烂才有可能一窥门径。 在本篇和续篇博文中,我们将和小伙伴们一起…

手把手教你绘制和解读实用R列线图(Nomogram):从入门到精通

一、引言 列线图&#xff08;Nomogram&#xff09;是一种常用的数据可视化工具&#xff0c;它能够直观地展示多个变量之间的关系&#xff0c;并帮助我们理解和解释复杂的数据模式。通过绘制列线图&#xff0c;我们可以将各种变量的影响和相互关联转化为图形化的表示&#xff0c…

2001-2021年各省高速公路里程数据

2001-2021年全国及各省高速公路里程数据 1、时间&#xff1a;2001-2021年 2、指标&#xff1a;高速公路里程 3、范围&#xff1a;全国及30个省市 &#xff08;不含西藏&#xff09; 4、来源&#xff1a;各省NJ、省TJGB、第三产业TJNJ &#xff08;无缺失&#xff09; 5、指…

鸿蒙项目方舟框架(ArkUI)之线性布局容器Stack组件

鸿蒙项目方舟框架&#xff08;ArkUI&#xff09;之线性布局容器Stack组件 一、操作环境 操作系统: Windows 10 专业版、IDE:DevEco Studio 3.1、SDK:HarmonyOS 3.1 二、Stack组件 堆叠容器&#xff0c;子组件按照顺序依次入栈&#xff0c;后一个子组件覆盖前一个子组件。 …

docker Mysql-udf-http

1.Mysql-udf-http镜像已上传到dockerhub中 docker pull heidaodageshiwo/mysql-udf-http:v1 2.启动镜像(默认密码root1234) docker run -tid -p 3306:3306 --namemysql-udf-http --privilegedtrue heidaodageshiwo/mysql-udf-http:v1 3.命令 [rootlocalhost ~]# docker im…

Navisworks各版本安装指南

Navisworks 下载链接 https://pan.baidu.com/s/1DGD9TbSa6Xjd-HoySd5AYg?pwd0531 1.鼠标右击【Navisworks2024(64bit)】压缩包&#xff08;win11及以上系统需先点击“显示更多选项”&#xff09;【解压到 Navisworks2024(64bit)】。 2.打开解压后的文件夹&#xff0c;双击打…

大甩卖-(CWRU)轴承故障诊数据集和代码全家桶

Python-凯斯西储大学&#xff08;CWRU&#xff09;轴承数据解读与分类处理 Python轴承故障诊断 (一)短时傅里叶变换STFT Python轴承故障诊断 (二)连续小波变换CWT_pyts 小波变换 故障-CSDN博客 Python轴承故障诊断 (三)经验模态分解EMD_轴承诊断 pytorch-CSDN博客 Pytorch…

大数据规模存储的几个核心问题

文章目录 三个关键问题RAID&#xff08;独立磁盘冗余阵列&#xff09;RAID是如何解决关于存储的三个关键问题&#xff1f;水平伸缩 大规模数据存储都需要解决几个核心问题&#xff0c;这些问题都是什么呢&#xff1f; 三个关键问题 1.数据存储容量的问题 既然大数据要解决的…

ROS TF坐标变换 - TF树

目录 一、TF树介绍二、TF2与TF三、构建TF树四、rviz查看TF坐标关系 一、TF树介绍 在机器人系统中&#xff0c;存在运动学模型和动力学模型。对于刚体机器人&#xff0c;动力学模型基于刚体动力学&#xff0c;代表机器人系统在运动过程中力/力矩与其运动状态的变化关系。而运动…

(五)分文件编程

文章目录 为什么要引入分文件编程.C文件怎么添加.H文件怎么书写以及如何进行链接.H书写格式&#xff1a;“有头有尾标识符”例如&#xff08;timer.h) .H链接链接到头文件所在路径的文件夹路径即可 提供一个分文件编程的一种代码最后附上视频演示 为什么要引入分文件编程 C程序…

Linux基础知识学习2

tree命令的使用 可以看到dir2目录下的这些文件&#xff0c;要想显示dir2的具体结构&#xff0c;可用tree命令 mv命令 它可以实现两个功能 1.将文件移动到另一个目录中 2.对某一个文件进行重命名 1.将文件移动到另一个目录中 这里将dir1中的2.txt移动到他的子目录dir3中 执行…

【linux】cat的基本使用

cat是一个常用的命令&#xff0c;用来显示文本的内容&#xff0c;合并和创建文本文件 类似命令还有显示文件开头的内容&#xff1a; 【linux】head的用法 输出文件开头的内容-CSDN博客 显示文件末尾的内容&#xff1a; 【linux】tail的基本使用-CSDN博客 当我们想到了想要…

JVM工作原理与实战(三):字节码文件的组成

专栏导航 JVM工作原理与实战 RabbitMQ入门指南 从零开始了解大数据 目录 专栏导航 前言 一、基础信息 1.Magic魔数 2.主副版本号 3.其他信息 二、常量池 1.案例解析 三、方法 1.方法介绍 2.案例解析 四、字段 五、属性 总结 前言 JVM作为Java程序的运行环境&…

字母简化(UPC练习)

题目描述 给出一串全部为小写英文字母的字符串&#xff0c;要求把这串字母简化。简化规则是&#xff1a;统计连续出现的字母数&#xff0c;输出时先输出个数&#xff0c;再输出字母。比如&#xff1a;aaabbbaa&#xff0c;则简化为3a3b2a&#xff1b;而zzzzeeeeea&#xff0c;…

堆的应用:堆排序和TOP-K问题

上次才讲完堆的相关问题&#xff1a;二叉树顺序结构与堆的概念及性质&#xff08;c语言实现堆 那今天就接着来进行堆的主要两方面的应用&#xff1a;堆排序和TOP-K问题 文章目录 1.堆排序1.1概念、思路及代码1.2改良代码&#xff08;最初建立大堆用AdjustDow&#xff09; 2. TO…

个人简历范本(精选5篇)

HR浏览一份简历也就25秒左右&#xff0c;如果你连「好简历」都没有&#xff0c;怎么能找到好工作呢&#xff1f; 如果你不懂得如何在简历上展示自己&#xff0c;或者觉得怎么改简历都不出彩&#xff0c;那请你一定仔细读完。 个人求职简历第 1 篇 男 22 本科 AI简历 市场营…