GO第二天学习

本文详细介绍了Go语言中的指针概念,包括类型指针和切片的差异,以及它们在内存管理和安全性上的优势。接着,讨论了new和make函数的使用及区别,展示了如何通过结构体和匿名结构体来创建对象。此外,文章还涵盖了方法的接收者、接口类型及其使用,以及错误处理中的Error接口。通过对Go语言基础的深入探讨,帮助读者更好地理解和应用Go语言。

GO指针

区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针

指针在Go语言中可以被拆分为两个核心概念:
类型指针 允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。
切片 由指向起始元素的原始指针、元素数量和容量组成。

受益于这样的约束和拆分,Go语言的指针类型变量即拥有指针高效访问的特点,又不会发生指针偏移,从而避免了非法修改关键性数据的问题。同时,垃圾回收也比较容易对不会发生偏移的指针进行检索和回收。

切片比原始指针具备更强大的特性,而且更为安全。切片在发生越界时,运行时会报出宕机,并打出堆栈,而原始指针只会崩溃。

func modify1(x int) {
	x = 100
}
func modify2(x *int) {
	*x = 100
}
func main() {
	a := 10
	modify1(a)
	fmt.Println(a) // 10
	modify2(&a)
	fmt.Println(a) // 100
}

new和make函数

func new(Type) *Type
返回一个指针类型,所以可以用 new来分配内存并且创建指针

var str *string
str = new(string)
*str = "helloworld"
fmt.Println(*str)

func make(t Type, size ...IntegerType) Type
给一个数据类型,开辟多大空间,最后返回该数据类型

func main() {
	var b map[string]int
	b = make(map[string]int, 10)
	b["张三"] = 100
	fmt.Println(b)
}

new与make的区别
都可以用来做内存分配
make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身
new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针

结构体

Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念
Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性

type person struct {
	name string
	city string
	age  int8
}
func main() {
	var p1 person
	p1.name = "张三"
	p1.city = "北京"
	p1.age = 18
	fmt.Printf("p1=%v\n", p1)
	//p1={张三 北京 18}
	fmt.Printf("p1=%+v\n", p1)
	//p1={name:张三 city:北京 age:18}
	fmt.Printf("p1=%#v\n", p1)
	//p1=main.person{name:"张三", city:"北京", age:18}
}
 %v  只输出值
 %+v 输出对应键值
 %#v 输出结构体名{对应键值}

匿名结构体
就不是 type 定义了,而是 var

func main() {
    var user struct{Name string; Age int}
    user.Name = "小王子"
    user.Age = 18
    fmt.Printf("%#v\n", user)
}

还可以 new 函数来创建指针类型的结构体,得到的是结构体的地址

src := new(person)
src.name = "aaa"
src.city = "bbb"
src.age = 15
fmt.Printf("%+v", src)

结构体匿名字段

type Person struct {
	string
	int
}
//main.Person{string:"北京", int:18}

并不是没有字段名,而是默认把类型名当做字段名
构造函数

Go语言没有构造函数的功能,但是我们可以使用结构体初始化的过程来模拟实现构造函数

type person struct {
	name string
	city string
	age  int8
}
func newperson(name string, city string, age int8) *person {
	return &person{
		name: name,
		city: city,
		age:  age,
	}
}
func main() {
	src := newperson("张三", "北京", 18)
	fmt.Printf("%+v", src)
	//&{name:张三 city:北京 age:18}
}

父子关系的结构体的构造和初始化——模拟父级构造调用

type Cat struct {
    Color string
    Name  string
}
type BlackCat struct {
    Cat  
    // 嵌入Cat, 类似于派生,实例化时,BlackCat 中的 Cat 也会一并被实例化。
}
// “构造基类”
func NewCat(name string) *Cat {
    return &Cat{
        Name: name,
    }
}
// “构造子类”
func NewBlackCat(color string) *BlackCat {
    cat := &BlackCat{}
    cat.Color = color
    return cat
}

方法的接收者

func (接收者变量 接收者类型) 方法名(参数列表) (返回参数){}

func (self Person) age_1(age int8) {
	self.age = age
}
func (self *Person) age_2(age int8) {
	self.age = age
}
func main() {
	p1 := NewPerson("张三", 18)
	p1.age_1(10)
	fmt.Printf("%+v", p1)
	p1.age_2(100)
	fmt.Printf("%+v", p1)
}

p1 是person 结构体类型,所以可以调用 Dream函数
age_1 中是值类型的接收者,无法修改变量本身的值
age_2 中是指针类型的接收者,所以是可以修改值的

注意
结构体中字段大写开头表示可公开访问,小写表示私有(仅在定义当前结构体的包中可访问)

结构体标签 Tag

Tag是结构体的元信息,可以在运行的时候通过反射的机制读取出来。
Tag在结构体字段的后方定义,由一对反引号包裹起来

type Student struct {
	ID     int    `json:"id"` //通过指定tag实现json序列化该字段时的key
	Gender string //json序列化是默认使用字段名作为key
	name   string //私有不能被json包访问
}
func main() {
	s1 := Student{
		ID:     1,
		Gender: "男",
		name:   "张三",
	}
	data, _ := json.Marshal(s1)
	fmt.Printf("json str:%s\n", data)
	//json str:{"id":1,"Gender":"男"}
}

Go导包

import (
    f "fmt"
    o "os"
	_ "encoding/json"
)
可以自定义别名,也可以只加载这个包,加载这个包中的资源初始化,init 函数将被执行且仅执行一遍

Go语言中不允许引入包却不在代码中使用这个包,如果引入了未使用的包则会触发编译错误

init 函数初始化

func init(){}

不接收任何参数也没有任何返回值,代码中也不能主动调用它
一个包的初始化过程是按照代码中引入的顺序来进行的,所有在该包中声明的 init 函数都将被串行调用并且仅调用执行一次。
每一个包初始化的时候都是先执行依赖的包中声明的init函数再执行当前包中声明的 init 函数。确保在程序的main函数开始执行时所有的依赖包都已初始化完成。
在这里插入图片描述

Go接口

type 接口名 interface{
    方法名1( 参数列表1 ) 返回值列表1
    方法名2( 参数列表2 ) 返回值列表2
}

接口类型变量

假设Dog 和Cat 类型均实现了Sayer 接口,此时一个Sayer类型的变量就能够接收Cat和Dog类型的变量

var x Sayer // 声明一个Sayer类型的变量x
a := Cat{}  // 声明一个Cat类型变量a
b := Dog{}  // 声明一个Dog类型变量b
x = a       // 可以把Cat类型变量直接赋值给x
x.Say()     // 喵喵喵
x = b       // 可以把Dog类型变量直接赋值给x
x.Say()     // 汪汪汪

同一个类型实现不同的接口互相不影响使用
一个接口的所有方法,也不一定需要由一个类型完全实现
接口的方法可以通过在类型中嵌入其他类型或者结构体来实现

// WashingMachine 洗衣机
type WashingMachine interface {
	wash()
	dry()
}
// 甩干器
type dryer struct{}

// 实现WashingMachine接口的dry()方法
func (d dryer) dry() {
	fmt.Println("甩一甩")
}
// 海尔洗衣机
type haier struct {
	dryer //嵌入甩干器
}
// 实现WashingMachine接口的wash()方法
func (h haier) wash() {
	fmt.Println("洗刷刷")
}

接口和接口可以相互嵌套,接口和结构体也可以嵌套

空接口

空接口是指没有定义任何方法的接口类型
因此任何类型都可以视为实现了空接口
所以空接口类型的变量可以存储任意类型的值

var x interface{}
x = "张三"
fmt.Printf("%T", x)

空接口可以作为函数的参数,接收任意类型的参数
空接口可以作为map 的值,接收任意类型的值

接口值

接口类型的值可以是任意一个实现了该接口的类型值
所以接口值除了需要记录具体值之外,还需要记录这个值属于的类型
也就是说接口值由“类型”和“值”组成,这两部分会根据存入值的不同而发生变化,我们称之为接口的动态类型和动态值
在这里插入图片描述

类型断言

x.(T)
意思是 x 可能是 T类型的
返回两个参数,第一个参数是x转化为T类型后的变量,第二个值是一个布尔值
若为true则表示断言成功,为false则表示断言失败。

var n Mover = &Dog{Name: "旺财"}
v, ok := n.(*Dog)
if ok {
	fmt.Println("类型断言成功")
	// 变量v是*Dog类型
} else {
	fmt.Println("类型断言失败")
}

Error接口

Go 语言中的错误处理与其他语言不太一样,它把错误当成一种值来处理
更强调判断错误、处理错误,不支持其他语言中使用try/catch捕获异常的方式。

当一个函数或方法需要返回错误时,通常是把错误作为最后一个返回值。例如标准库 os 中打开文件的函数。

//Go 语言中使用一个名为 error 接口来表示错误类型。
type error interface {
    Error() string
}


func Open(name string) (*File, error) {
	return OpenFile(name, O_RDONLY, 0)
}
if err != nil {
	fmt.Println("打开文件失败,err:", err)
	return
}

由于 error 是一个接口类型,默认零值为nil。
所以我们通常将调用函数返回的错误与nil进行比较,以此来判断函数是否返回错误。

自定义错误

// errors 包提供的New函数创建一个错误。
func New(text string) error


func queryById(id int64) (*Info, error) {
	if id <= 0 {
		return nil, errors.New("无效的id")
	}
}
多源动态最优潮流的分布鲁棒优化方法(IEEE118节点)(Matlab代码实现)内容概要:本文介绍了基于Matlab实现的多源动态最优潮流的分布鲁棒优化方法,适用于IEEE118节点电力系统。该方法旨在应对电力系统中源荷不确定性带来的挑战,通过构建分布鲁棒优化模型,有效处理多源输入下的动态最优潮流问题,提升系统运行的安全性和经济性。文中详细阐述了模型的数学 formulation、求解算法及仿真验证过程,并提供了完整的Matlab代码实现,便于读者复现与应用。该研究属于电力系统优化调度领域的高水平技术复现,具有较强的工程实用价值。; 适合人群:具备电力系统基础知识和Matlab编程能力的研究生、科研人员及从事电力系统优化调度的工程技术人员,尤其适合致力于智能电网、鲁棒优化、能源调度等领域研究的专业人士。; 使用场景及目标:①用于电力系统多源环境下动态最优潮流的建模与求解;②支撑含可再生能源接入的电网调度决策;③作为鲁棒优化方法在实际电力系统中应用的教学与科研案例;④为IEEE118节点系统的仿真研究提供可复现的技术支持。; 阅读建议:建议结合提供的Matlab代码逐模块分析,重点关注不确定变量的分布鲁棒建模、目标函数构造及求解器调用方式。读者应具备一定的凸优化和电力系统分析基础,推荐配合YALMIP工具包与主流求解器(如CPLEX、Gurobi)进行调试与扩展实验。
内容概要:本文系统介绍了物联网与云计算的基本概念、发展历程、技术架构、应用场景及产业生态。文章阐述了物联网作为未来互联网的重要组成部分,通过RFID、传感器网络、M2M通信等技术实现物理世界与虚拟世界的深度融合,并展示了其在智能交通、医疗保健、能源管理、环境监测等多个领域的实际应用案例。同时,文章强调云计算作为物联网的支撑平台,能够有效应对海量数据处理、资源弹性调度和绿色节能等挑战,推动物联网规模化发展。文中还详细分析了物联网的体系结构、标准化进展(如IEEE 1888、ITU-T、ISO/IEC等)、关键技术(中间件、QoS、路由协议)以及中国运营商在M2M业务中的实践。; 适合人群:从事物联网、云计算、通信网络及相关信息技术领域的研究人员、工程师、高校师生以及政策制定者。; 使用场景及目标:①了解物联网与云计算的技术融合路径及其在各行业的落地模式;②掌握物联网体系结构、标准协议与关键技术实现;③为智慧城市、工业互联网、智能物流等应用提供技术参考与方案设计依据;④指导企业和政府在物联网战略布局中的技术选型与生态构建。; 阅读建议:本文内容详实、覆盖面广,建议结合具体应用场景深入研读,关注技术标准与产业协同发展趋势,同时结合云计算平台实践,理解其对物联网数据处理与服务能力的支撑作用。
标题基于Java的停车场管理系统设计与实现研究AI更换标题第1章引言介绍停车场管理系统研究背景、意义,分析国内外现状,阐述论文方法与创新点。1.1研究背景与意义分析传统停车场管理问题,说明基于Java系统开发的重要性。1.2国内外研究现状综述国内外停车场管理系统的发展现状及技术特点。1.3研究方法以及创新点介绍本文采用的研究方法以及系统开发中的创新点。第2章相关理论总结Java技术及停车场管理相关理论,为系统开发奠定基础。2.1Java编程语言特性阐述Java的面向对象、跨平台等特性及其在系统开发中的应用。2.2数据库管理理论介绍数据库设计原则、SQL语言及在系统中的数据存储与管理。2.3软件工程理论说明软件开发生命周期、设计模式在系统开发中的运用。第3章基于Java的停车场管理系统设计详细介绍系统的整体架构、功能模块及数据库设计方案。3.1系统架构设计阐述系统的层次结构、模块划分及模块间交互方式。3.2功能模块设计介绍车辆进出管理、车位管理、计费管理等核心功能模块设计。3.3数据库设计给出数据库表结构、字段设计及数据关系图。第4章系统实现与测试系统实现过程,包括开发环境、关键代码及测试方法。4.1开发环境与工具介绍系统开发所使用的Java开发环境、数据库管理系统等工具。4.2关键代码实现展示系统核心功能的部分关键代码及实现逻辑。4.3系统测试方法与结果阐述系统测试方法,包括单元测试、集成测试等,并展示测试结果。第5章研究结果与分析呈现系统运行效果,分析系统性能、稳定性及用户满意度。5.1系统运行效果展示通过截图或视频展示系统实际操作流程及界面效果。5.2系统性能分析从响应时间、吞吐量等指标分析系统性能。5.3用户满意度调查通过问卷调查等方式收集用户反馈,分析用户满意度。第6章结论与展望总结研究成果,提出系统改进方向及未来发展趋势。6.1研究结论概括基于Java的停车场管理
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

paidx0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值