Go语言学习(一)

Go语言基础

Go语言官网:https://golang.org/

go中文社区:https://studygolang.com

go中文在线文档:https://studygolang.com/pkgdoc

第一个程序

注释:

  1. 单行注释 //
  2. 多行注释 /*  */

// 第一个程序 project main.go
// 导入主函数的包
package main

// 系统会导入所需的包   format 标准输入输出包
import (
	"fmt"
)

func main() {
	//在屏幕打印helloworld  
	fmt.Println("helloworld")

}

变量

变量:在程序运行过程中其值能够改变的量 成为变量 变量存在内存中

内存:一个连续的数据集合,每一个内存存储区域都有唯一的地址标识,称为内存地址

计算机能够识别的数据形式 :二进制(0 1 10 11 100)

八进制(0 1 2 3 4 5 6 7)

十进制(0 1 2 3 4 5 6 7 8 9 10)

十六进制(0 1 2 3 4 5 6 7 8 9 A(10)B(11)C(12) D(13) E(14)F(15)10)

#定义和声明的区别是是否赋值
var 变量名 数据类型            //变量声明
var a int

var 变量名 数据类型 = 值       //变量定义
var a int=10

变量名:=值                   //自动推导类型
a:=10

多重赋值格式

变量1,变量2:=值1,值2
a,b:=10,20

交换a,b的值

# 第一种方法:
temp = a
a = b
b = temp
# 第二种方法:
a = a + b
b = a - b
a = a - b
# 第三种方法:
a, b = b, a
fmt.Println(a, b)

匿名变量

接收这个数据,但是不做存储

_,b,c:=10,20,30
	fmt.Println(b,c) 

输出格式

    # Println  打印数据时自动换行
	# Println  打印数据不换行
	# %d 占位符 表示输出一个整形数据
	# %f 占位符 表示输出一个浮点型数据
	# \n 表示转义字符  相当于换行符
	# %f 占位符 默认保留6位小数
	# %3f  表示小数点后面保留三位 会对第四位进行四舍五入
	# bool布尔 	string字符串 byte字符
	# 声明bool类型变量 默认值为 false true
	# %t 占位符 表示输出一个布尔类型数据
	# %s 占位符 表示输出一个字符串类型数据
	# %c 占位符 表示输出一个字符类型数据

格式化输入输出

&:取地址运算符

    fmt.Println()  //输出数据 自带换行
    fmt.Print()    //输出数据 不带换行
    fmt.Printf()   //格式化输出数据  %d 整型 %f 浮点型 %t 布尔类型 %s 字符串类型 %c 字符类型 %p 内存地址
	var name string
	var passwd string
	fmt.Println("请输入用户名")
	fmt.Scanf("%s",&name)
	fmt.Println("请输入密码")
	fmt.Scanf("%s",&passwd)
	fmt.Println(name,passwd) 

数据类型

布尔型

var a bool

浮点型

var a float64

字符串类型

var a string

字符和字符串的区别

在go语言中汉字是3个字符,为了和linux同一处理

func main() {
	//计算字符串的个数
	var b string = "传智播客"
	num := len(b)
	fmt.Println(num)	
}
12

常量

常量:在程序运行过程中  其值不能发生改变的量称之为常量

常量的存储位置在数据区,不能通过& 取地址来访问,变量的存储位置在栈区 系统会为没一个应用程序分配1M空间用来存储变量,在程序运行结束后会自动释放

const B int = 30 //常量一般用大写字母表示

iota枚举

func main() {
	const (
		a = iota //0  
		b = iota //1  
		c = iota //2  
		d = iota //3
	)
fmt.Println(a, b, c, d)
0 1 2 3
func main() {
	const (
		a    = iota
		b, c = iota, iota
		d, e
	)
	fmt.Println(a, b, c, d, e)
}
0 1 1 2 2

算术运算符,赋值运算符,逻辑运算符,关系运算符

流程控制

if

func main() {
	var a, b, c int
	fmt.Println("请输入三只小猪的体重")
	fmt.Scan(&a, &b, &c)
	if a > b {
		if a > c {
			fmt.Println("a重")
		} else {
			fmt.Println("c重")
		}
	} else {
		if a < b {
			if b > c {
				fmt.Println("b重")
			} else {
				fmt.Println("c重")
			}
		}
	}
}

switch

//if 可以嵌套 可以判断区间  执行效率比较低
//switch 执行效率高 整洁  不能嵌套和区间判断
func main() {
	var w int
	fmt.Scan(&w)
    //switch中的值不能是浮点型数据  浮点型数据是一个约等于数据
	switch w {
	case 1:
		fmt.Println("今天是星期一")
	case 2:
		fmt.Println("今天是星期二")
	case 3:
		fmt.Println("今天是星期三")
        //如果输入的值没有找到 默认进入default
    default:
		fmt.Println("输入错误")
	}
}
fallthrough //让switch执行下一个分支的代码 如果不写  执行到下一个分支就会自动停止
1 3 5 7 8 10 12 月份都是31天,我们可以这样写
func main() {
	var w int
	fmt.Scan(&w)
	switch w {
	case 1:
		fallthrough
	case 3:
		fallthrough
	case 5:
		fallthrough
	case 12:
		fmt.Println("31天")
	default:
		fmt.Println("输入错误")
	}
}

for

基本语法结构如下:

for 表达式1;表达式2;表达式3{

循环体

}

表达式1:定义一个循环的变量,记录循环的次数

表达式2:一般为循环条件,循环多少次

表达式3:一般为改变循环条件的代码,使循环条件终有一天不再成立

循环体:重复要做的事情。

表达式2为假的时候,for循环停止

//打印1-10
func main01() {
	//for函数格式 i是在函数内部定义的 不能在外部进行使用
	for i := 1; i <= 10; i++ {
		fmt.Println(i)
	}
}
//计算1-100的总和
func main() {
	sum := 0
	for i := 1; i <= 100; i++ {
		sum = sum + i
	}
	fmt.Println(sum)
}

循环嵌套

嵌套循环中  执行次数为外层*内层

func main() {

	for i := 0; i < 5; i++ {

		for j := 0; j < 5; j++ {
			fmt.Println(i, j)
		}

	}
}

跳出循环

break //在循环中 跳出循环
continue//结束本次循环 继续下次循环
func main05() {
	//break  在循环中跳出循环
	//在嵌套循环中 跳出本层循环

	for i:=0;i<=100;i++ {
		//奇数
		if i%2==1{
			//结束本次循环继续下次循环
			continue
		}
		fmt.Println(i)
	}
}
//
导出所有偶数

练习

水仙花:一个三位数,100-999 各个位数的立方和如果等于这个数本身,这个数就是一个水仙花数

func main() {
	for i := 100; i < 1000; i++ {
		a := i / 100
		b := i % 100 / 10
		c := i % 10
		if a*a*a+b*b*b+c*c*c == i {
			fmt.Println(i)
		}
	}
}

函数

定义

func 函数名(函数参数列表){       
        代码体/函数体
}

在函数定义过程中 函数的参数称为形参 形式参数

形参和实参是不同的存储单元 在函数调用过程中 不会相互影响
在函数调用中使用的是实参  在函数定义中使用的形参

func add(a int, b int) {
	var sum int
	sum = a + b
	fmt.Println(sum)
}

func main() {
	var a, b int
	fmt.Scanf("%d", &a) // 取地址运算符
	fmt.Scanf("%d", &b)
	add(a, b)

}

不定参函数调用

不定参函数 : 函数参数类型为 ...数据类型

func add(arr ...int) {
	sum := 0
	for i := 0; i < len(arr); i++ {
		sum = sum + arr[i]
	}
	fmt.Println(sum)

}
func main() {
	add(1, 2, 3, 455)
	add(1, 2, 1, 32, 656)
}
//
461
692

用range遍历元素信息 有两个返回值 必须接受 第一个值是下标 第二个值是数据值

func add(arr ...int) {  //前面的名字自定义
	sum := 0
    for i := 0; i < len(arr); i++ {  len()计算不定参数的长度
		sum = sum + arr[i]
	}
	fmt.Println(sum)

}
func plus(are ...int) {
	sum := 0
    //用range遍历元素信息 有两个返回值 必须接受 第一个值是下标 第二个值是数据值
	for _, data := range are {  //_,匿名变量   丢弃数据不进行处理 在这里我们用不到下标所以丢弃
        						//date 也可以自定义
		sum = sum + data
	}
	fmt.Println(sum)
}
func main() {
	plus(1, 2, 3, 455)
	add(1, 2, 1, 32, 656)
}

函数嵌套调用

函数的作用域是全局的  可在项目的任意文件使用  不需要在意先后顺序想

func test1(a int, b int) {
	sum := a + b
	fmt.Println(sum)

}
func test2(a1 int, b1 int) {
	test1(a1, b1)
}
func main() {
	test2(1, 2)
}
3
func test1(arr ...int) {
	for i := 0; i < len(arr); i++ {
		fmt.Println(i, arr[i])
	}
}
func test2(b ...int) {
    //如果函数参数为不定参  传递方式为b[0:]...
	test1(b[0:]...)
    //从下标为2开始传
    test1(b[2:]...)
}
func main() {
	test2(1, 1, 1, 1, 1)
}

函数返回值

格式:func 函数名(形参列表)返回值类型列表{代码体}

return可以写一个表达式  将表达式的结果作为返回值

return表示函数的结束return后面的代码不会执行  同时return会把函数的返回值 传递给主调函数

func sub(a int, b int) int {
    sum := a - b
    fmt.Println(sum)
    return sum
    fmt.Println("ssss")
    fmt.Println("ssdd")
    return 0
}
func main() {
    sub(10, 30)
}

以上代码也可改成

func sub(a int, b int) (value int) {
	sum := a - b
	fmt.Println(sum)
	return value
	fmt.Println("ssss")
	fmt.Println("ssdd")
	return 0
}
func main() {
	sub(10, 30)
}

函数多个返回值

func test() (a, b, c int) {
	a, b, c = 1, 5, 6
	return
}
func main() {
    //函数的返回值可以为主调函数赋值   可以通过返回值改变实参数据
    //如果函数有多个返回值 但是不使用返回值 可以用匿名变量接收数据
	a, _, c := test()
	fmt.Println(a, c)
}

函数类型

type可以定义函数类型

type可以为已存在的类型起别名

我们可以看到下面test1的函数类型被定义为TYPE1   test2 和test3同理被定义为TYPE2和TYPE3

func test1() {
	fmt.Println("askdkasj")
}
func test2(a int, b int) {
	fmt.Println(a + b)
}
func test3(a int, b int) int {
	return a * b
}
//type可以定义函数类型
//type可以为已存在的类型起别名
type TYPE1 func()
type TYPE2 func(int, int)
type TYPE3 func(int, int) int

func main() {
    //定义函数类型变量
	var f TYPE1

	f = test1
    //通过函数变量调用函数
	f()
    //函数类型  其实就是一个指针
	var f1 TYPE2
	var f2 TYPE3
	f2 = test3
	v := f2(3, 5)
	fmt.Println(v)

	f1 = test2
	f1(10, 30)
}

函数数据作用域

1.局部变量:在函数内部定义的变量  作用域限定于本函数的内部  从变量定义到本函数结束有效

2.在同一作用域范围内 变量名是唯一的

3.程序中 如果出现了相同的变量名 如果本函数有自己的变量 就使用自己的 如果没有上外层寻找变量

4.如果名字相同会采用就近原则 使用自己的变量 

func main() {
	a := 10
	{
		a := 355
		fmt.Println(a)
	}
	fmt.Println(a)
}
355
10

5.全局变量:在函数外部定义的变量称为全局变量

6.全局变量作用域是项目中的所有文件

7.全局变量在内存中数据区存储  和const定义的常量存储位置都是数据区

var a int = 10 //如果全局变量没有初始值为0
//全局常量
const b int = 66
func demo() {
	fmt.Println(b)
	fmt.Println(a)
}
func main() {
	demo()
	//采用就近原则使用局部变量
	//在局部变量作用域范围内  全局变量不起作用
	a := 35
	fmt.Println(a)
}
66
10
35

匿名函数

前面我们定义函数的时候,发现是不能在一个函数中,再次定义一个函数。如果我们想在一个函数中再定义一个函数,那么可以使用匿名函数,所谓匿名函数就是没有名字的函数。

func main() {
	a := 10
	b := 20
	//匿名内部函数
	func(a int, b int) {
		fmt.Println(a + b)
	}(a, b)

}
func main() {
	a := 10
	b := 20
	//f是函数类型对应的变量
	f := func(a int, b int) {
		fmt.Println(a + b)
	}
	f(a, b)
	f(20, 30)
}
func main() {
	a := 10
	b := 20
	//匿名函数  带返回值的匿名函数
	f := func(a int, b int) int {
		return a + b
	}	
	//函数调用	f 函数类型 v 接受返回值  类型为int
	v := f(a, b)
	fmt.Println(v)
}

闭包

//可以通过匿名函数和闭包实现函数在栈区的本地化操作
func test2() func() int {
	var a int
	return func() int {
		a++
		return a
	}
}
func main() {
	//将test2函数类型赋值给f
	//f := test2   返回值类型是func func ()int
	//函数调用将test2的返回值给f
	f := test2() //返回值类型是func()int
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
	fmt.Printf("%T", f)
}

递归函数

如果一个函数在内部不调用其他的函数,而是自己本身的话,这个函数就是递归函数。递归很消耗资源,消耗内存。能不使用尽量不会使用。

//计算阶乘
// 根据递归计算阶乘
package main
import (
	"fmt"
)

var sum int = 1

func test(n int) {
	if n == 1 {
		return
	}
	test(n - 1)
	sum *= n
}

func main() {
	test(5)
	fmt.Println(sum)

}
120

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值