当前位置: 首页 > news >正文

Golang学习第一天笔记总结

GoLang学习

  • Golang的优势
    • 极简单的部署方式
    • 静态类型语言
    • 语言层面的并发
    • 强大的标准库
    • 简单易学
  • 第一个go程序
  • 变量
    • 变量的声明
    • 常量
  • 函数
    • 多返回值
    • init函数与import导包
  • defer
    • defer和return谁先谁后
  • slice切片
    • 声明方式
    • 使用方式
      • 切片容量的追加
      • 切片的拷贝
  • map
    • 三种声明方式
    • 使用方式
  • 面向对象特征
    • 结构体struct
    • class封装
    • 继承
    • 多态
    • 万能数据类型
  • 反射

Golang的优势

极简单的部署方式

  • 可直接编译成机器码
  • 不依赖其他库
  • 直接运行即可部署

静态类型语言

  • 编译的时候检查出来隐藏的大多数问题

语言层面的并发

  • 天生的基因支持
  • 充分的利用多核

强大的标准库

  • runtime系统调度机制
  • 高效的GC垃圾回收
  • 丰富的标准库

简单易学

  • 25个关键字
  • C语言简洁基因,内嵌C语法支持
  • 面向对象特征(继承、多态、封装)
  • 跨平台

第一个go程序

  • 嗨嗨嗨,依旧是经典的hello world
  • 注意:在go里面,函数的{一定是和函数名在同一行的,否则会编译错误
package mainimport "fmt"func main() {fmt.Printf("hello world")
}

变量

变量的声明

  • 一共有四种变量的声明方式:
    1. 声明一个变量,默认的值是0
    2. 声明一个变量并初始化
    3. 在初始化的时候可以省去数据类型,通过值自动匹配当前的变量的数据类型
    4. 省去var关键字 — 只能用在函数内部,不能用来声明全局变量
package mainimport "fmt"func main() {// 方法一:声明一个变量,默认的值是0var a intfmt.Printf("a=%d\n", a)// 方法二:声明一个变量并初始化var b int = 10fmt.Printf("b=%d\n", b)// 方法三:在初始化的时候,可以省去数据类型,通过值自动匹配当前的变量的数据类型var c = 100fmt.Printf("c=%d,%T\n", c, c)// 方法四:省去var关键字(常用) --- 只能用在函数内部e := 100fmt.Println(e)fmt.Printf("e=%d,%T\n", e, e)// 声明多个变量var x1, x2 int = 100, 200fmt.Printf("x1=%d,x2=%d\n", x1, x2)// 多行的多变量声明var (y1 int = 1000y2 int = 2000)fmt.Printf("y1=%d,y2=%d\n", y1, y2)
}

常量

  • 使用const进行声明,具有只读属性
  • 可以在const()中添加一个关键字iota,每行的iota都会累加1,第一行的iota的默认值是0
  • iota只能配合const()一起使用,iota只有在const进行累加效果
package mainimport "fmt"// const来定义枚举类型
const (Up = iota // iota = 0;DownLeftRight
)func main() {const length int = 100fmt.Println("length=", length)// 打印枚举类型fmt.Println("Up=", Up)  //0fmt.Println("Down=", Down) //1fmt.Println("Left=", Left) //2fmt.Println("Right=", Right) //3
}

函数

多返回值

  • 可以分为两种,返回值是匿名的和返回值是具名
  • 有形参名称的(具名)他们的作用域是这个函数体内部
package mainimport "fmt"// 返回多个返回值,匿名
func getSumAndSub(a int, b int) (int, int) {sum := a + bsub := a - breturn sum, sub
}// 返回多个返回值,命名
func getSumAndSub2(a int, b int) (sum int, sub int) {sum = a + bsub = a - breturn
}func main() {res1, res2 := getSumAndSub(10, 5)fmt.Println("res1=", res1)fmt.Println("res2=", res2)res3, res4 := getSumAndSub2(10, 5)fmt.Println("res3=", res3)fmt.Println("res4=", res4)
}

init函数与import导包

  • import导包:
    1. import _ "fmt":给fmt包起一个别名,匿名,无法使用当前包的方法,但是会执行当前的包内部的init方法
    2. import bb "fmt":给fmt包起一个别名—bb,bb.Println()可以直接调用
    3. import . "fmt":将当前的fmt包中的全部方法,导入到当前本包的作用域中,fmt包中的全部方法可以直接使用API来调用,不需要fmt.API来调用
  • 目录结构如图
    在这里插入图片描述
  • lib1
package lib1import "fmt"func Lib1Test() {fmt.Println("lib1Test ...")
}func init() {fmt.Println("lib1 init ...")
}
  • lib2
package lib2import "fmt"func Lib2Test() {fmt.Println("lib2Test ...")
}func init() {fmt.Println("lib2 init ...")
}
  • main.go
package mainimport ("5-init/lib1""5-init/lib2""fmt"
)func main() {fmt.Println("main ...")lib1.Lib1Test()lib2.Lib2Test()
}
  • 运行结果如图
    在这里插入图片描述

defer

  • 在 Go 语言里,defer 就像一个“延迟执行的小秘书”:它把任务(函数或语句)压进栈里,等当前函数即将返回前才按后进先出的顺序统一执行,无论函数是正常结束还是 panic 崩溃都要先处理完这些“遗愿”。因此它最常用来做资源清理(关闭文件、解锁互斥量、释放锁等),保证成对操作绝不遗漏,代码也更简洁直观。
package mainimport "fmt"func main() {defer fmt.Println("main end")fmt.Println("main start")fmt.Println("main middle")
}

defer和return谁先谁后

  • return之后的语句先执行,defer之后的语句后执行

slice切片

  • 创建的数组为动态数组
  • 并且函数中传递的参数也为引用传递,而且不同元素长度的动态数组他们的形参是一致的
package mainimport "fmt"func printArray(array []int) {// 引用传递// _表示匿名的变量for _, value := range array {fmt.Println("value=", value)}array[0] = 1000
}func main() {// 动态数组myArray := []int{1, 2, 3, 4}printArray(myArray)fmt.Println("-------")for i := 0; i < len(myArray); i++ {fmt.Println(myArray[i])}
}

声明方式

  1. slice1 := []int{1,2,3}:声明slice1是一个切片,并且初始化,默认值是1,2,3,长度len是3
  2. var slice1 []int + slice1 = make([]int,3):声明slice1是一个切片,但是并没有给slice分配空间
  3. var slice1 []int = make([]int,3):声明slice1是一个切片,同时给slice分配空间,3个空间,初始化值为0

使用方式

切片容量的追加

  • lencap:切片的长度和容量不同,长度表示左指针至右指针之间的距离,容量表示左指针至底层数组末尾的距离
  • 切片的扩容机制:append的时候,如果长度增加后超过了容量,则将容量增加2倍
package mainimport "fmt"func main() {var numbers = make([]int, 3, 5)fmt.Println(len(numbers), cap(numbers), numbers)// 想numbers切片追加一个元素2numbers = append(numbers, 2)fmt.Println(len(numbers), cap(numbers), numbers)// 想numbers切片追加一个元素3numbers = append(numbers, 3)fmt.Println(len(numbers), cap(numbers), numbers)// 想numbers切片追加一个元素4numbers = append(numbers, 4)fmt.Println(len(numbers), cap(numbers), numbers)}
  • 输出结果
    在这里插入图片描述

切片的拷贝

  • copy可以将底层数组的切片一起进行拷贝

map

三种声明方式

  • 第一种:
	// 声明myMap1是一种map类型,key是string,value是stringvar myMap1 map[string]stringif myMap1 == nil {fmt.Println("myMap1是一个空map")}// 在使用map前,需要先用make给map分配数据空间myMap1 = make(map[string]string, 10)myMap1["one"] = "java"myMap1["two"] = "c++"myMap1["three"] = "python"fmt.Println(myMap1)
  • 第二种声明方式
	// --- 第二种声明方式myMap2 := make(map[int]string)myMap2[1] = "java"myMap2[2] = "js"myMap2[3] = "go"fmt.Println(myMap2)
  • 第三种声明方式
	// --- 第三种声明方式myMap3 := map[string]string{"one":   "php","two":   "c++","three": "python",}fmt.Println(myMap3)

使用方式

  • 典型的增删改查
  • 传给函数的依然是引用传递
package mainimport "fmt"func main() {// 声明一个mapstudentMap := make(map[int]string)// 添加studentMap[1] = "熊大"studentMap[2] = "熊二"studentMap[3] = "光头强"// 遍历for key, value := range studentMap {fmt.Println(key, value)}// 删除delete(studentMap, 3) // 删除强哥// 修改studentMap[2] = "吉吉"fmt.Println("------------")// 遍历for key, value := range studentMap {fmt.Println(key, value)}
}
  • 输出结果
    在这里插入图片描述

面向对象特征

结构体struct

  • 与C语言的结构体差不多
package mainimport "fmt"// 声明一种行的数据类型 myint,是int的一个别名
type myint int// 定义一个结构体
type Book struct {title stringauth  stringprice int
}func main() {var a myint = 10fmt.Printf("a=%d,%T\n", a, a)var b1 Bookb1.auth = "miraculous"b1.price = 99b1.title = "go_learn"fmt.Println(b1)
}

class封装

  • 类名、属性名、方法名首字母大写表示对外(其他包)可以访问,否则只能够在本包内访问
package mainimport "fmt"// 如果类名首字母大写,表示其他包也能够访问
type Student struct {// 如果属性的首字母大写,表示该属性是对外能够访问的,否则的话只能够类的内部访问name stringage  int
}// func (this Student) Show() {
// 	fmt.Println(this)
// }// func (this Student) GetName() {
// 	fmt.Println(this.name)
// }// func (this Student) SetName(newName string) {
// 	// this 是调用该方法的对象的一个副本
// 	this.name = newName
// }func (this *Student) Show() {fmt.Println(this.age, this.name)
}func (this *Student) GetName() {fmt.Println(this.name)
}func (this *Student) SetName(newName string) {this.name = newName
}func main() {s1 := Student{name: "熊大", age: 10}s1.Show()s1.SetName("光头强")s1.Show()}
  • 输出结果
    在这里插入图片描述

继承

  • 示例代码
package mainimport "fmt"type Human struct {name stringage  int
}func (this *Human) Walk() {fmt.Println("Human Walk ...")
}func (this *Human) Eat() {fmt.Println("Human Eat ...")
}// 超人继承Human的属性
type SuperMan struct {Human //表示继承level int
}// 重写父类的Eat方法
func (this *SuperMan) Eat() {fmt.Println("SuperMan Eat ...")
}// 加入新的方法
func (this *SuperMan) Fly() {fmt.Println("SuperMan fly ...")
}func main() {h1 := Human{"zhangsan", 18}fmt.Println(h1)h1.Eat()h1.Walk()var sh1 SuperMansh1.name = "熊大"sh1.age = 10sh1.level = 100sh1.Eat()sh1.Walk()sh1.Fly()
}
  • 运行结果
    在这里插入图片描述

多态

  • 多态就是“同一接口,不同实现”:代码里只写一次调用,运行时才根据对象的实际类型决定具体干什么,就像同一颗遥控器按钮,遥控电视就换台,遥控音响就切歌,调用者无需关心细节,只管发出指令。
  • 特点:
    1. 有一个父类(有接口)
    2. 有子类(实现了父类的全部接口方法)
    3. 父类类型的变量(指针)指向(引用)子类的具体数据变量
  • 示例代码
package mainimport "fmt"// 本质是一个指针
type AnimalIF interface {Sleep()GetColor() stringGetType() string
}// 具体的类
type Cat struct {color string
}type Dog struct {color string
}func (this *Cat) Sleep() {fmt.Println("Cat is sleeping")
}func (this *Cat) GetColor() string {return this.color
}func (this *Cat) GetType() string {return "Cat"
}func (this *Dog) Sleep() {fmt.Println("Dog is sleeping")
}func (this *Dog) GetColor() string {return this.color
}func (this *Dog) GetType() string {return "Dog"
}// 接口
func showAnimal(animal AnimalIF) {animal.Sleep()fmt.Println("color=", animal.GetColor())fmt.Println("kind=", animal.GetType())
}func main() {cat := Cat{"Green"}dog := Dog{"Yellow"}showAnimal(&cat)showAnimal(&dog)
}
  • 运行效果
    在这里插入图片描述

万能数据类型

  • interface{}是万能数据类型
  • 那么interface{}应该如何区分此时引用的底层数据类型是什么?----- 类型断言

反射

  • 反射(Reflection)是一种语言级元编程机制,允许运行中的程序以自描述方式查询、访问并修改自身结构——包括类型信息、字段、方法、接口、标签等——而无需在编译期显式知晓这些成员的名称与签名;凭借该能力,程序可在执行期动态实例化任意类型、调用任意函数、读写私有状态,实现依赖注入、序列化、动态代理、框架级配置解析等高阶功能。
http://www.dtcms.com/a/619581.html

相关文章:

  • 用jsp实现网站开发实例wordpress去除评论
  • 【Java常用API】-----System 与 标准 I/O流
  • 网站access数据库被攻击不断增大北京市建设投标网站
  • 6.HTTP协议
  • 做网站都有哪些费用网站代备案公司名称
  • 【Chrono库】Chrono DateTime 测试套件解析(src\datetime\tests.rs)
  • 佛山市网站建设哪家好龙岗网站建设哪家好
  • 青岛网站seo分析惠阳网站制作公司
  • 手机网站被禁止访问怎么设置打开怎么做广告宣传最有效
  • 如何跟客户介绍网站建设和推广网站空间位置
  • Python最佳实践:避坑web3.py,稳健gunicorn
  • “状态层同步”是什么,为什么重要,它是怎么工作的
  • 熟悉网站空间 域名等相关知识全球十大搜索引擎入口
  • 什么叫做网站整站微信营销网站(含html源文件)免费下载
  • 佛山市建设企业网站服务机构视频制作软件手机版
  • 济宁专业建网站wordpress首页添加一个超链接框
  • 建站特别慢wordpress建设一网站有什么用
  • 萝岗电子商务网站建设搜索引擎优化有哪些要点
  • 湖南it网站建设mxtia大理工程建设信息网站
  • 金仓数据库 KES:以 “五位一体” 破局,打造融合数据库标杆
  • 三门峡市住房建设局网站网络推广优化seo
  • OSPF协议配置实验报告
  • 江门企业做网站兴义做网站的公司
  • 25年11月软考架构真题《论软件系统的性能测试》考后复盘总结
  • 17zwd一起做网站广州新塘微网站分享功能
  • 高清品牌网站设计建设网站安全制度体系的建设情况
  • 网站设计鉴赏房子装修设计图片大全
  • Selenium 八大定位方法
  • 做网站业务的怎么找资源seo公司推荐推广平台
  • 【开题答辩全过程】以 基于web网络的超级商场进行销存管理系统为例,包含答辩的问题和答案