golang语言_1

Go 语言的 SDK 是什么?
SDK 就是软件开发工具包。我们做 Go 开发,首先需要先安装并配置好 sdk.
Golang 环境变量配置及其作用。
GOROOT: 指定 go sdk 安装目录。
Path: 指令 sdk\bin 目录:go.exe godoc.exe gofmt.exe
GOPATH: 就是 golang 工作目录:我们的所有项目的源码都这个目录下。
Golang 程序的编写、编译、运行步骤是什么?能否一步执行?
编写:就是写源码
编译:go build 源码 =》 生成一个二进制的可执行文件
运行:1. 对可执行文件运行 xx.exe ./可执行文件 2. go run 源码
Golang 程序编写的规则

  1. go 文件的后缀 .go
  2. go 程序区分大小写
  3. go 的语句后,不需要带分号
  4. go 定义的变量,或者 import 包,必须使用,如果没有使用就会报错
  5. go 中,不要把多条语句放在同一行。否则报错
  6. go 中的大括号成对出现,而且风格 func main() { //语句 }
    为什么需要变量
    变量是程序的基本组成单位
    变量相当于内存中一个数据存储空间的表示,通过变量名可以访问到变量值
    变量的使用步骤
    1.声明变量
    2.非变量赋值
    3.使用变量
    变量的注意事项
  7. 变量表示内存中的一个存储区域
  8. 该区域有自己的名称(变量名)和类型(数据类型)
  9. Golang 变量使用的三种方式
    (1) 第一种:指定变量类型,声明后若不赋值,使用默认值
    (2) 第二种:根据值自行判定变量类型(类型推导)
    (3) 第三种:省略 var, 注意 :=左侧的变量不应该是已经声明过的,否则会导致编译错误
    4)如何一次性声明多个全局变量【在 go 中函数外部定义变量就是全局变量】:
var (
	n1 = 1
	n2 = 2
	name = "tom"
)

5)该区域的数据值可以在同一类型范围内不断变化(重点)

func main(){
	var i int = 10
	i = 20
	fmt.Println("i=",i)
	i = 1.2//int 不能改变数类型
}

6)变量在同一个作用域(在一个函数或者在代码块)内不能重名
7)变量=变量名+值+数据类型
8) Golang 的变量如果没有赋初值,编译器会使用默认值, 比如 int 默认值 0 string 默认值为空串, 小数默认为 0
数据类型
基本数据类型:数值,字符型,布尔型,字符串
派生/复杂数据类型:1.指针2.数组3.结构体4.管道5.函数6.切片7.接口8.map
整型的使用细节

  1. Golang 各整数类型分:有符号和无符号,int uint 的大小和系统有关。
  2. Golang 的整型默认声明为 int 型
  3. 如何在程序查看某个变量的字节大小和数据类型 (使用较多)
  4. Golang 程序中整型变量在使用时,遵守保小不保大的原则,即:在保证程序正确运行下,尽量 使用占用空间小的数据类型。【如:年龄】
  5. bit: 计算机中的最小存储单位。byte:计算机中基本存储单元。[二进制再详细说] 1byte = 8 bit
    浮点类型
    说明:float64 的精度比 float32 的要准确.
    说明:如果我们要保存一个精度高的数,则应该选用 float64
    浮点型的存储分为三部分:符号位+指数位+尾数位 在存储过程中,精度会有丢失
    字符类型本质探讨
    1.字符型 存储到 计算机中,需要将字符对应的码值(整数)找出来 存储:字符—>对应码值---->二进制–>存储 读取:二进制----> 码值 ----> 字符 --> 读取
    2.字符和码值的对应关系是通过字符编码表决定的(是规定好)
    3.Go 语言的编码都统一成了 utf-8。非常的方便,很统一,再也没有编码乱码的困扰了
    布尔类型
  6. 布尔类型也叫 bool 类型,bool 类型数据只允许取值 true 和 false
  7. bool 类型占 1 个字节。
  8. bool 类型适于逻辑运算,一般用于程序流程控制
    string类型
    字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本
    指针
    1.基本数据类型,变量存的就是值,也叫值类型
    2.获取变量的地址,用&,比如: var num int, 获取 num 的地址:&num 分析一下基本数据类型在内存的布局.
    3.指针类型,指针变量存的是一个地址,这个地址指向的空间存的才是值 比如:var ptr int = &num
    4.获取指针类型所指向的值,使用:
    ,比如:var ptr int, 使用ptr 获取 ptr 指向的值
    指针的使用细节
    1.值类型,都有对应的指针类型, 形式为 *数据类型,比如 int 的对应的指针就是 int, float32 对应的指针类型就是 float32, 依次类推。
    2.值类型包括:基本数据类型 int 系列, float 系列, bool, string 、数组和结构体 struct
    3.引用类型:指针、slice 切片、map、管道 chan、interface 等都是引用类型
    运算符的基本介绍
    1)算术运算符 ±
    / ++ – %
    2)赋值运算符
    3)比较运算符/关系运算符
    4)逻辑运算符
    5)位运算符
    6)其它运算符
    算术运算符使用注意事项
    1)对于除号 “/”,它的整数除和小数除是有区别的:整数之间做除法时,只保留整数部分而舍弃 小数部分。 例如: x := 19/5 ,结果是 3
    2)当对一个数取模时,可以等价 a%b=a-a/b
    b , 这样我们可以看到 取模的一个本质运算。
    3)Golang 的自增自减只能当做一个独立语言使用时,不能这样使用
    4)Golang 的++ 和 – 只能写在变量的后面,不能写在变量的前面,即:只有 a++ a-- 没有 ++a --a
    5)Golang 的设计者去掉 c / java 中的 自增自减的容易混淆的写法,让 Golang 更加简洁,统一。(强 制性的)
    关系运算符(比较运算符)
    1)关系运算符的结果都是 bool 型,也就是要么是 true,要么是 false
    2)关系表达式 经常用在 if 结构的条件中或循环结构的条件中
    3)关系运算符组成的表达式,我们称为关系表达式: a > b
  9. 比较运算符"=="不能误写成 “=” !!
    赋值运算符
  10. 运算顺序从右往左
  11. 赋值运算符的左边 只能是变量,右边 可以是变量、表达式、常量值
  12. 复合赋值运算符等价于下面的效果 比如:a += 3 等价于 a = a + 3
    运算符优先级
    1.括号 ++ –
    2.单目运算
    3.算术运算符
    4.移位运算符
    5.关系运算符
    6.位运算符
    7.逻辑运算符
    8.赋值运算符
    9.逗号
    键盘输入语句
    1)导入 fmt 包
    2)调用 fmt 包的 fmt.Scanln() 或者 fmt.Scanf()
    进制转换
    1.二进制转十进制
    从最低位开始,将每个位数提取出来,乘以2的(位数-1)次方,然后求和
    2.八进制转十进制
    从最低位开始,将每个位数提取出来,乘以8的(位数-1)次方,然后求和
    3.十六进制转十进制
    从最低位开始,将每个位数提取出来,乘以16的(位数-1)次方,然后求和
    4.十进制转二进制
    将该数不断除以2,直到商为0,然后将每步得到的余数倒过来,就是对应的二进制
    5.十进制转八进制
    将该数不断除以8,直到商为0,然后将每步得到的余数倒过来,就是对应的二进制
    6.十进制转八进制
    将该数不断除以16,直到商为0,然后将每步得到的余数倒过来,就是对应的二进制
    7.二进制转八进制
    将二进制数每三位一组(从最低位开始组合),转成对应的八进制数即可
    8.二进制转成十六进制
    将二进制数每四位一组(从最低位开始组合),转成对应的十六进制数即可
    9.八进制转二进制
    将八进制数每一位,转成对应的一个3位的二进制数即可
    10.十六进制转八进制
    将十六进制数每一位,转成对应的一个4位的二进制数即可
    源码 反码 补码
    在这里插入图片描述
    位运算符 移位运算符
    Golang 中有 3 个位运算
    分别是”按位与&、按位或|、按位异或^,
    它们的运算规则是:
    按位与& : 两位全为1,结果为 1,否则为 0
    按位或| : 两位有一个为 1,结果为 1,否则为 0
    按位异或 ^ : 两位一个为 0,一个为 1,结果为 1,否则为 0
    在这里插入图片描述
    Golang 中有 2 个移位运算符: >>、<< 右移和左移,
    运算规则:
    右移运算符 >>:低位溢出,符号位不变,并用符号位补溢出的高位
    左移运算符 <<: 符号位不变,低位补 0
    a := 1 >> 2 // 0000 0001 =>0000 0000 = 0
    c := 1 << 2 // 0000 0001 ==> 0000 0100 => 4
    程序流程控制
    1)顺序控制
    2)分支控制
    3)循环控制
    分支控制
    (1)单分支
    if条件表达式{ }
func main() {
	var age int
	fmt.Println("请输入你的年龄")
	fmt.Scanln(&age)
	if age > 18 {
		fmt.Println("你已经成年了")
	}
}

(2)单分支的细节说明
golang支持在if中,直接定义一个变量

func main() {
	if age := 20;age > 18 {
		fmt.Println("你已经成年了")
	}
}

(3)双分支

func main() {
	var age int
	fmt.Println("请输入你的年龄")
	fmt.Scanln(&age)
	if age > 18 {
		fmt.Println("你已经成年了")
	} else {
		fmt.Println("你还是未成年")
	}
}

(4)双分支里面的else不能换行
(5) math.Sqrt( ) 求平方根
(6) 嵌套分支布艺过多,建议3层内
switch分支控制
1)switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上到下逐一测 试,直到匹配为止。
2)匹配项后面也不需要再加 break
switch分支控制总结
1)switch 的执行的流程是,先执行表达式,得到值,然后和 case 的表达式进行比较,如果相等, 就匹配到,然后执行对应的 case 的语句块,然后退出 switch 控制。
2)如果 switch 的表达式的值没有和任何的 case 的表达式匹配成功,则执行 default 的语句块。执行后退出 switch 的控制.
3)golang 的 case 后的表达式可以有多个,使用 逗号 间隔.
4)golang 中的 case 语句块不需要写 break , 因为默认会有,即在默认情况下,当程序执行完 case 语 句块后,就直接退出该 switch 控制结构。

func main() {
	var week byte
	fmt.Println("请输入")
	fmt.Scanf("%c", &week)
	switch week {
		case 'a':
			fmt.Println("周一")
		default:
			fmt.Println("周二")
	}
}

switch 的使用的注意事项和细节
1)case/switch 后是一个表达式( 即:常量值、变量、一个有返回值的函数等都可以)
2)case 后的各个表达式的值的数据类型,必须和 switch 的表达式数据类型一致
3)case 后面可以带多个表达式,使用逗号间隔。比如 case 表达式 1, 表达式 2 …
4)case 后面的表达式如果是常量值(字面量),则要求不能重复
5)case 后面不需要带 break , 程序匹配到一个 case 后就会执行对应的代码块,然后退出 switch,如 果一个都匹配不到,则执行 default
6)default 语句不是必须的.
7)switch 后也可以不带表达式,类似 if --else 分支来使用。

switch {
	case week > 80 :
		fmt.Println("优秀")
	default:
		fmt.Println("不及格")
	}

8)switch 后也可以直接声明/定义一个变量,分号结束,不推荐。
9)switch 穿透-fallthrough ,如果在 case 语句块后增加 fallthrough ,则会继续执行下一个 case,也 叫 switch 穿透
10)Type Switch:switch 语句还可以被用于 type-switch 来判断某个 interface 变量中实际指向的 变量类型
在这里插入图片描述
switch 和 if 的比较
1)如果判断的具体数值不多,而且符合整数、浮点数、字符、字符串这几种类型。建议使用 swtich 语句,简洁高效。
2)其他情况:对区间判断和结果为 bool 类型的判断,使用 if,if 的使用范围更广。
for循环控制
第一种写法
for 循环变量初始化; 循环条件; 循环变量迭代 { 循环操作(语句) }

for i := 0; i <= 10; i++ {
		fmt.Println("你好")
	}

第二种写法

func main() {
	i := 0
	for i <= 10{
		fmt.Println("你好")
		i++
	}
}

第三种写法

func main() {
	k := 0
	for {
		if k <=10{
			fmt.Println("你好")
		}else{
			break //break就是跳出这个循环
		}
		k++
	}
}

Golang 提供 for-range 的方式,可以方便遍历字符串和数组
对应 for-range 遍历方式而言,是按照字符方式遍历。因此如果有字符串有中文,也是 ok

func main() {
	var str string = "hello北京"
	str2 := []rune(str) //把str转成[]rune
	for i := 0; i < len(str2); i++ {
		fmt.Printf("%c \n", str2[i])
	}

	for index, val := range str2 {
		fmt.Printf("index=%d,val=%c \n", index, val)
	}
}

1-100是9的倍数的个数 和 相加之后的和

func main() {
	var max uint64 = 100
	var count uint64 = 0
	var sum uint64 = 0
	var i uint64 = 1
	for ; i <= max; i++ {
		if i%9 == 0 {
			count++
			sum += i
		}
	}
	fmt.Printf("%v , %v \n", count, sum)
}

while和do…while
Go 语言没有 while 和 do…while 语法,这一点需要同学们注意一下,如果我们需要使用类似其它语 言(比如 java / c 的 while 和 do…while ),可以通过 for 循环来实现其使用效果。
while的实现

func main() {
	var i int = 1
	for {
		if i > 10{
			break
		}
		fmt.Println(i)
		i++
	}
}

do…while的实现

func main() {
	var i int = 1
	for {
		fmt.Println("hello,word", i)
		i++
		if i > 10 {
			break
		}
	}
}

1) 统计 3 个班成绩情况,每个班有 5 名同学,求出各个班的平均分和所有班级的平均分[学生的成 绩从键盘输入]

func main() {
	var totalSum float64 = 0.0
	for j := 1; j <= 3; j++ {
		sum := 0.0
		for i := 1; i <= 5; i++ {
			var score float64
			fmt.Printf("请输入第%d个班,第%d个学生的成绩\n", j, i)
			fmt.Scanln(&score)
			sum += score
		}
		fmt.Printf("第%d个班级的平均分是%v", j, sum/5)
		totalSum += sum

	}
	fmt.Printf("所有班的总成绩是%v,平均分是%v", totalSum, totalSum/(15))
}

2) 统计三个班及格人数,每个班有 5 名同学

func main() {
	var totalSum float64 = 0.0
	var passCount int = 0
	for j := 1; j <= 3; j++ {
		sum := 0.0
		for i := 1; i <= 5; i++ {
			var score float64
			fmt.Printf("请输入第%d个班,第%d个学生的成绩\n", j, i)
			fmt.Scanln(&score)
			sum += score
			if score >= 60 {
				passCount++
			}
		}
		fmt.Printf("第%d个班级的平均分是%v", j, sum/5)
		totalSum += sum

	}
	fmt.Printf("所有班的总成绩是%v,平均分是%v", totalSum, totalSum/(15))
	fmt.Printf("及格人数是%v", passCount)
}

金字塔

func main() {
	var totalLevel = 5
	//i 层数
	for i := 1; i <= totalLevel; i++ {
		for k := 1; k <= totalLevel-i; k++ {
			fmt.Print(" ")
		}
		//j 每层多少个
		for j := 1; j <= i*2-1; j++ {
			if j == 1 || j == 2*i-1 || i == totalLevel {
				fmt.Print("*")
			} else {
				fmt.Print(" ")
			}
		}
		fmt.Println()
	}
}

在这里插入图片描述

九九乘法表

func main() {
	//i层数
	for i := 1; i <= 9; i++ {
		for j := 1; j <= i; j++ {
			fmt.Printf("%v * %v =%v \t", j, i, j*i)
		}
		fmt.Println()
	}
}

在这里插入图片描述
跳转控制语句-break
1-100 生成99 用了多少次 随机数

func main() {
	count := 0
	for {
		rand.Seed(time.Now().UnixNano())
		var n = rand.Intn(100) + 1
		count++
		if n == 99 {
			break
		}
	}
	fmt.Println("生成了", count)
}

1)break 语句出现在多层嵌套的语句块中时,可以通过标签指明要终止的是哪一层语句块
1)break 默认会跳出最近的 for 循环
2)break 后面可以指定标签,跳出标签对应的 for 循环

1) 100 以内的数求和,求出 当和 第一次大于 20 的当前数

func main() {
	sum := 0
	for i := 1; i <= 100; i++ {
		sum += i
		if sum > 20 {
			fmt.Println("次数是", i)
			break
		}

	}
}

2) 实现登录验证,有三次机会,如果用户名为”张无忌” ,密码”888”提示登录成功,否则提示 还有几次机会

func main() {
	var name string
	var pwd string
	var loginChance = 3
	for i := 1; i <= 3; i++ {
		fmt.Println("输入用户名")
		fmt.Scanln(&name)
		fmt.Println("输入用密码")
		fmt.Scanln(&pwd)
		if name == "张无忌" && pwd == "888" {
			fmt.Println("登陆成功")
			break
		} else {
			loginChance--
			fmt.Printf("登录失败还剩%v次 \n", loginChance)
		}
		if loginChance == 0 {
			fmt.Println("机会用完")
		}
	}
}

跳转控制语句-continue
continue 语句用于结束本次循环,继续执行下一次循环。
continue 语句出现在多层嵌套的循环语句体中时,可以通过标签指明要跳过的是哪一层循环 , 这 个和前面的 break 标签的使用的规则一样
跳转控制语句-goto
1)Go 语言的 goto 语句可以无条件地转移到程序中指定的行。
2)goto 语句通常与条件语句配合使用。可用来实现条件转移,跳出循环体等功能。
3)在 Go 程序设计中一般不主张使用 goto 语句, 以免造成程序流程的混乱,使理解和调试程序 都产生困难
** 跳转控制语句-return**
1)如果 return 是在普通的函数,则表示跳出该函数,即不再执行函数中 return 后面代码,也可以 理解成终止函数
2)如果 return 是在 main 函数,表示终止 main 函数,也就是说终止程序。
函数的基本概念
为完成某一功能的程序指令(语句)的集合,称为函数
在 Go 中,函数分为: 自定义函数、系统函数(查看 Go 编程手册)
函数的基本语法

func 函数名(形参列表)(返回值列表)  {
	执行语句
	return 返回值列表
}

包使用的注意事项和细节讨论
1)在给一个文件打包时,该包对应一个文件夹,比如这里的 utils 文件夹对应的包名就是 utils, 文件的包名通常和文件所在的文件夹名一致,一般为小写字母。
2)当一个文件要使用其它包函数或变量时,需要先引入对应的包
引入方式 1:import “包名”
引入方式 2: import ( “包名” “包名” )
package 指令在 文件第一行,然后是 import 指令。
在 import 包时,路径从 $GOPATH 的 src 下开始,不用带 src , 编译器会自动从 src 下开始引入
3)为了让其它包的文件,可以访问到本包的函数,则该函数名的首字母需要大写,类似其它语言 的 public ,这样才能跨包访问。比如 utils.go 的
4)在访问其它包函数,变量时,其语法是 包名.函数名, 比如这里的 main.go 文件中
5)如果包名较长,Go 支持给包取别名, 注意细节:取别名后,原来的包名就不能使用了
6)在同一包下,不能有相同的函数名(也不能有相同的全局变量名),否则报重复定义
7)如果你要编译成一个可执行程序文件,就需要将这个包声明为 main , 即 package main .这个就 是一个语法规范,如果你是写一个库 ,包名可以自定义
函数的递归调用
一个函数在函数体内又调用了本身,我们称为递归调用
代码示意

func test(n int) {
	if n > 2 {
		n--
		test(n)
	}
	fmt.Println("n=", n)
}
func test2(n int) {
	if n > 2 {
		n--
		test2(n)
	} else {
		fmt.Println("n=", n)
	}
}
func main() {
	test2(4)
}

test输出 2,2,3 test2输出 2
函数递归需要遵守的重要原则
1)执行一个函数时,就创建一个新的受保护的独立空间(新函数栈)
2)函数的局部变量是独立的,不会相互影响
3)递归必须向退出递归的条件逼近,否则就是无限递归,死规了:
4)当一个函数执行完毕,或者遇到 return,就会返回,遵守谁调用,就将结果返回给谁,同时当函数执行完毕或者返回时,该函数本身也会被系统销毁
函数使用的注意事项和细节讨论
1)函数的形参列表可以是多个,返回值列表也可以是多个。
2)形参列表和返回值列表的数据类型可以是值类型和引用类型。
3)函数的命名遵循标识符命名规范,首字母不能是数字,首字母大写该函数可以被本包文件和其 它包文件使用,类似 public , 首字母小写,只能被本包文件使用,其它包文件不能使用,类似 privat
4)函数中的变量是局部的,函数外不生效
5)基本数据类型和数组默认都是值传递的,即进行值拷贝。在函数内修改,不会影响到原来的值。
6)如果希望函数内的变量能修改函数外的变量(指的是默认以值传递的方式的数据类型),可以传 入变量的地址&,函数内以指针的方式操作变量。从效果上看类似引用 。

// n1 就是 *int 类型
func test03(n1 *int) {
	fmt.Printf("n1的地址 %v\n",&n1)
	*n1 = *n1 + 10
	fmt.Println("test03() n1= ", *n1) // 30
}
func main() {
	// num := 20
	// test02(num)
	// fmt.Println("main() num= ", num)

	num := 20
	fmt.Printf("num的地址=%v\n", &num)
	test03(&num)
	fmt.Println("main() num= ", num) // 30
}

7)Go 函数不支持函数重载

func test02(n1 int) {
	
	n1 = n1 + 10
	fmt.Println("test02() n1= ", n1)
}

func test02(n1 int , n2 int) {
	
}

8)在 Go 中,函数也是一种数据类型,可以赋值给一个变量,则该变量就是一个函数类型的变量 了。通过该变量可以对函数调用

func getSum(n1 int, n2 int) int {
	return n1 + n2
}

func main() {
	
	a := getSum
	fmt.Printf("a的类型%T, getSum类型是%T\n", a, getSum)
	}

9)函数既然是一种数据类型,因此在 Go 中,函数可以作为形参,并且调用

res:=myFun(getsum,50,60)
fmt.Println("res2=",res2)
//函数既然是一种数据类型,因此在Go中,函数可以作为形参,并且调用
func myFun(funvar func(int, int) int, num1 int, num2 int ) int {
	return funvar(num1, num2)
}
  1. 为了简化数据类型定义,Go 支持自定义数据类型 基本语法:type 自定义数据类型名 数据类型
    // 理解: 相当于一个别名 案例:type myInt int
    // 这时 myInt 就等价 int 来使用了.
    案例:type mySum func (int, int) int // 这时 mySum 就等价 一个 函数类型 func (int, int) int
// 给int取了别名 , 在go中 myInt 和 int 虽然都是int类型,但是go认为myInt和int两个类型
	type myInt int 

	var num1 myInt // 
	var num2 int
	num1 = 40
	num2 = int(num1) //各位,注意这里依然需要显示转换,go认为myInt和int两个类型
	fmt.Println("num1=", num1, "num2=",num2)

	//再加一个案例
	//这时 myFun 就是 func(int, int) int类型
	type myFunType func(int, int) int
	
	//函数既然是一种数据类型,因此在Go中,函数可以作为形参,并且调用
	func myFun2(funvar myFunType, num1 int, num2 int ) int {
		return funvar(num1, num2)
	}
	//看案例
	res3 := myFun2(getSum, 500, 600)
	fmt.Println("res3=", res3)

11)支持对函数返回值命名

//支持对函数返回值命名
func getSumAndSub(n1 int, n2 int) (sum int, sub int){
	sub = n1 - n2
	sum = n1 + n2
	return
}
//看案例
	a1, b1 := getSumAndSub(1, 2)
	fmt.Printf("a=%v b=%v\n", a1, b1)
  1. 使用 _ 标识符,忽略返回值
  2. Go 支持可变参数
//案例演示: 编写一个函数sum ,可以求出  1到多个int的和
//可以参数的使用
func sum(n1 int, args... int) int {
	sum := n1 
	//遍历args 
	for i := 0; i < len(args); i++ {
		sum += args[i]  //args[0] 表示取出args切片的第一个元素值,其它依次类推
	}
	return sum
}
//测试一下可变参数的使用
	res4 := sum(10, 0, -1, 90, 10,100)
	fmt.Println("res4=", res4)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值