结构体

创建结构体变量和访问结构体字段

package main

import "fmt"

//创建结构体变量和访问结构体字段
type Person struct {
Name string
Age int
} func main(){
//方式一
var p1 Person
p1.Name="牛魔王"
p1.Age=
fmt.Println(p1)
//方式二
p2:=Person{"mary",}
p2.Name="tome"
p2.Age=
fmt.Println(p2)
//方式三
var p3 *Person=new (Person)
//因为p3是指针,因此赋值方式
(*p3).Name="smith"//也可以这样写p3.Name="smith2"
//fmt.Println(*p3)
p3.Age=
fmt.Println(*p3)
//方式四
var person *Person=&Person{}//结构体指针
//person.Age=10和(*person).Age=88效果一样,因为
(*person).Name="scott"
person.Name="scott~~~"
(*person).Age=
person.Age=
//go编译器底层对person.Name做了转化(*person).Name fmt.Println(*person) }

结构体在内存中的体现

0.

package main

import "fmt"

//struct类型的内存分配机制
type Person struct{
Name string
Age int
} func main(){
var p1 Person p1.Age=
p1.Name="小明"
var p2 *Person=&p1
fmt.Println((*p2).Age)
fmt.Println(p2.Age)
p2.Name="tom~~"
fmt.Printf("p2.Name=%v p1.Name=%v\n",p2.Name,p1.Name)
fmt.Printf("p2.Name=%v p1.Name=%v\n",(*p2).Name,p1.Name) fmt.Printf("p1的地址%p\n",&p1)
fmt.Printf("p2的地址%p p2的值%\n",&p2,p2)
}

字段

1.在内存中的地址是连续的

package main

import "fmt"

//结构体所有字段在内存中是连续的
type Point struct {
x int
y int } //
type Rect struct {
leftUp,rightDown Point }
type Rect2 struct {
leftUp,rightDown *Point
} func main(){
r1:=Rect{Point{,},Point{,}}
//r1的四个int,在内存中是连续分布的
//打印地址
fmt.Printf("r1.leftUp.x地址=%p\nr1.leftUp.y地址=%p\nr1.rightDown.x地址=%p\nr1.rightDown.y地址%p\n",
&r1.leftUp.x,&r1.leftUp.y,&r1.rightDown.x,&r1.rightDown.y) //r2有两个*Point 这两个*Point类型的本身地址也是连续的
//但他们指向的地址不一定是连续的
r2:=Rect2{&Point{,},&Point{,}}
//打印本身地址
fmt.Printf("r2.leftUp本身地址=%p r2.rightDown 本身地址=%p \n",
&r2.leftUp,&r2.rightDown)
//打印指向地址
//他们指向的地址不一定是连续的
fmt.Printf("r2.leftUp指向地址=%p r2.rightDown指向地址=%p\n",
r2.leftUp,r2.rightDown)
}

2.结构体是单独定义的类型,与其他类型进行转换时需要有完全相同的字段(名字,个数,类型)

package main

import "fmt"

//结构体是单独定义的类型,与其他类型进行转换时需要有完全相同的字段(名字,个数,类型)
type A struct {
Num int
}
type B struct {
Num int
} func main(){
var a A
var b B
a=A(b)//可以转换
fmt.Println(a,b)
}

3.结构体进行type重新定义(相当于取别名),golang认为是新的数据类型,但是相互可以强转

package main

import "fmt"

//结构体进行type重新定义(相当于取别名),golang认为是新的数据类型,但是相互可以强转
type Student struct {
Name string
Age int
} //定义结构体
type Stu Student type integer int func main() {
var stu1 Student
var stu2 Stu
stu2 = Stu(stu1)
fmt.Println(stu1, stu2) var i integer=
var j int=
j=int(i)
fmt.Println(i,j)
}

4.struct的每个字段上,可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和饭序列化

package main

import (
"encoding/json"
"fmt"
)
//struct的每个字段上,可以写上一个tag,该tag可以通过反射机制获取,常见的使用场景就是序列化和饭序列化
type Monster struct {
Name string `json:"name"`//`json:"name"`就是struct tag
Age int `json:"age"`
Skill string `json:"skill"` }
func main(){
//1.创建一个Moster变量
monster:=Monster{"牛魔王",,"芭蕉扇"}
//2.将Master变量序列化为json格式字串
//json.Marsha1 函数中使用反射
jsonStr,err:=json.Marshal(monster)
if err!=nil{
fmt.Println("json 处理错误",err)
}
//
fmt.Println("jsonStr",string(jsonStr)) }

匿名结构体

//匿名结构体
func main() {
//匿名函数
res := func(a, b float64) float64 {
return math.Pow(a, b)
}(, )
fmt.Println(res)
//匿名结构体
addr := struct {
province, city string
}{"陕西省", "西安市"}
fmt.Println(addr)
cat := struct {
name, color string
age int8
}{
name: "绒毛",
color: "黑白",
age: ,
}
fmt.Println(cat)
}

结构体匿名字段

//结构体匿名字段
//同一类型的字段只有一个
type User struct {
string
byte
int8
float64
} func main() {
//实例化结构体
user := User{
"Steven",
'm',
,
177.5,
}
fmt.Println(user)
//数据依次打印
fmt.Printf("姓名:%s\n",user.string)
fmt.Printf("年龄:%d\n",user.int8)
fmt.Printf("身高:%.2f\n",user.float64)
fmt.Printf("性别:%c\n",user.byte)
}

方法

1.结构体是值类型,遵循值类型的传递机制

a

//结构体类型是值类型,如果改变结构体的变量,可以通过结构体的指针来实现

type Circle struct {
radius float64
}
func (c Circle) area() float64{
return 3.14*c.radius*c.radius
}
func (c *Circle) area2() float64{
(*c).radius=//等价于c.radius=10
return 3.14*c.radius*c.radius
}
func main(){
var c Circle
c.radius=4.0
res:=c.area()
fmt.Println("面积是",res)
//修改结构体的字段 res2:=c.area2()
fmt.Println(res2) }

b

2.使用结构体指针改变结构体变量

3.自定义struct可以有方法,int,float32也可以有方法

package main

import "fmt"

//自定义struct可以有方法,int,float32也可以有方法
type integer int func (i integer) print(){
fmt.Println("i=",i)
} func (i *integer) change(){
*i+=
} func main(){
var i integer=
i.print()
i.change()
fmt.Println("i=",i)
}

接受者为指针结构体和结构体的区别

//接受者是指针结构体和普通结构体的区别
//如果方法的接受者不是指针,实际只是获取一个拷贝,而不能真正改变接受者(结构体)中原来的数据 type Rectangle struct {
width, height float64
} //func
func (r Rectangle) setValue() {
fmt.Printf("setValue方法中r的地址:%p\n", &r)
r.height =
}
func (r *Rectangle) setValue2() {
fmt.Printf("setValue方法中r的地址:%p\n", &r)
r.height =
} func main() {
r1 := Rectangle{, }
r2 := r1
//打印对象的内存地址
fmt.Printf("r1的地址:%p\n", &r1)
fmt.Printf("r1的地址:%p\n", &r2)
r1.setValue()
fmt.Println("r1.height=", r1.height)
fmt.Println("r2.height=", r2.height)
r1.setValue2()
fmt.Println("r1.height=", r1.height)
fmt.Println("r2.height=", r2.height) }

4.访问范围控制规则,方法名首字母小写,只能本包访问

5.如果一个类型实现了String()这个方法,那么fmt.Println默认会调用这个变凉的String()进行输出

package main

import "fmt"
//如果一个类型实现了String()这个方法,那么fmt.Println默认会调用这个变凉的String()进行输出
type student struct{
Name string
Age int
} func (stu *student) String() string{
str:=fmt.Sprintf("Name=[%v] Age=[%v]",stu.Name,stu.Age)
fmt.Println("\nstring() 我被调用了\n")
return str
} func main(){
stu:=student{
Name:"tom",
Age:,
} fmt.Println(&stu)
}

练习

1.打印矩形

package main

import "fmt"

type MethodUtils struct {

}

func (mu MethodUtils) Print(){
for i:=;i<=;i++{
for j:=;j<=;j++{
fmt.Print("*")
}
fmt.Println()
}
} func (mu MethodUtils) Print2(m int,n int){
for i:=;i<=m;i++{
for j:=;j<=n;j++{
fmt.Print("*")
}
fmt.Println()
}
} //计算矩形面积
func (mu MethodUtils) area(len float64,width float64) float64{
return len*width
} //判断一个数是奇数还是偶数
func (mu *MethodUtils) JudgeNum(num int){
if num%=={
fmt.Println(num,"是偶数")
}else{
fmt.Println(num,"是奇数")
}
}
//根据行列,字符打印
func (mu *MethodUtils) Print3(n int,m int,key string){
for i:=;i<=n;i++{
for j:=;j<=m;j++{
fmt.Print(key)
}
fmt.Println()
}
}
func main(){
var mu MethodUtils
mu.Print()
mu.Print2(,)
fmt.Println(mu.area(,))
mu.JudgeNum()
mu.Print3(,,"~")
}

2.计算

package main

import "fmt"

type Cacuator struct {
Num1 float64
Num2 float64
} func (calcuator *Cacuator) getSum() float64 {
return calcuator.Num1 + calcuator.Num2
} func (calcuator *Cacuator) getSub() float64 {
return calcuator.Num1 - calcuator.Num2
} //方式二
func (calcuator *Cacuator) getRes(operator byte) float64 {
res := 0.0
switch operator {
case '+':
res = calcuator.Num1 - calcuator.Num2
case '-':
res = calcuator.Num1 - calcuator.Num2
case '*':
res = calcuator.Num1 * calcuator.Num2
case '/':
res = calcuator.Num1 / calcuator.Num2
default:
fmt.Println("运算符输入错误")
}
return res
}

3.值拷贝和地址拷贝

package main

import "fmt"

type Person struct {
Name string
}
//决定值拷贝还是地址拷贝看这个方法和哪个类型绑定
func test01(p Person) {
fmt.Println(p.Name)
} func test02(p *Person) {
fmt.Println(p.Name)
} //对于方法,接受者为值类型时,可以直接用指针类型的变量调用方法,反过来同样也可以
func (p Person) test03() {
p.Name = "jack"
fmt.Println("test03()=", p.Name)
}
func (p *Person) test04() {
p.Name = "mary"
fmt.Println("test03()=", p.Name)
} func main() {
p := Person{"tom"}
test01(p)
//对于普通函数,接受者为值类型时,不能将指针类型的数据直接传递,反之亦然
test02(&p) p.test03()
fmt.Println("main() p.name=", p.Name)
(&p).test03() //从形式上传入地址,但本质上仍是值拷贝
fmt.Println("main() p.name=",p.Name) (&p).test04()
fmt.Println("main() p.name=",p.Name)
p.test04()//等价于(&p).test04(),从形式上石传入值类型,但本质上仍是地址拷贝
}

应用案例

1.

package main

import (
"fmt"
) type Student struct {
name string
gender string
age int
id int
score float64
} func (student *Student) say() string{
infoStr:=fmt.Sprintf("student 的信息name=[%v],gender=[%v],age=[%v],id=[%v],score=[%v]",
student.name,student.gender,student.age,student.id,student.score)
return infoStr
} func main(){
var stu=Student{
name:"tom",
gender:"male",
age:,
id:,
score:99.98,
}
fmt.Println(stu.say())
}

2.计算面积

package main

import "fmt"

type Box struct {
len float64
width float64
height float64
} func (box *Box) getVolumn() float64 {
return box.len * box.width * box.height
} func main(){
var box Box
box.len=1.1
box.width=2.0
box.height=3.0
volumn:=box.getVolumn()
fmt.Printf("体积为=%2.f",volumn)
}

3.门票

package main

import "fmt"

//景区门票案例
//根据年龄判断价额
type Visitor struct{
Name string
AGe int
} func (visitor *Visitor) showPrice(){
if visitor.AGe>=||visitor.AGe<={
fmt.Println("考虑到安全,就不要玩了")
return
} if visitor.AGe>{
fmt.Printf("游客的名字为%v 年龄为%v 收费为20元\n",visitor.Name,visitor.AGe)
}else{
fmt.Printf("游客的名字为%v 年龄为%v 免费\n",visitor.Name,visitor.AGe)
}
} func main(){
var v Visitor
for{
fmt.Println("请输入你的名字")
fmt.Scanln(&v.Name)
if v.Name=="n"{
fmt.Println("退出程序")
}
fmt.Println("请输入你的年龄")
fmt.Scanln(&v.AGe)
v.showPrice()
} }

创建结构体实例时,指定字段的值

package main

import "fmt"

//创建结构体实例时,指定字段的值

type Stu struct{
Name string
Age int
} func main(){
//实例化时赋初始值
var stu1=Stu{"小明",}
stu2:=Stu{"小强",}
//下面这种方法可以不考虑顺序
var stu3=Stu{
Name: "jack",
Age: ,
}
stu4:=Stu{
Age:,
Name:"mary",
}
fmt.Println(stu1,stu2,stu3,stu4) //方式二
var stu5 *Stu=&Stu{"小王",}
stu6:=&Stu{"小王",}
var stu7=&Stu{
Name:"小东",
Age:, }
stu8:=&Stu{
Age:,
Name:"rose",
} fmt.Println(*stu5,*stu6,*stu7,*stu8)
}

工厂模式

mian/main.go

package main

import (
"fmt"
"oop/10.5.3/model"
)
//引入首字母小写的字段和方法
func main(){
var stu=model.NewStudent("tom",88.8)
fmt.Println(*stu)
fmt.Println("name=",stu.Name,"score=",stu.Score)
}

model/student.go

package model

type student struct{
Name string
Score float64
}
func NewStudent(n string,s float64) *student{
return &student{
Name:n,
Score:s,
}
}

面向对象三大特性

面向对象-抽象

package main

import "fmt"

type Account struct{
AccountNo string
Pwd string
Balance float64
} //存款
func (account *Account) Deposite(money float64,pwd string){
if pwd!=account.Pwd{
fmt.Println("你输入的密码不正确")
return
} if money<={
fmt.Println("你输入的金额不正确")
return
}
account.Balance+=money
fmt.Println("存款成功")
} //取款
func (account *Account) WidthDraw(money float64,pwd string){
if pwd!=account.Pwd{
fmt.Println("你输入的密码不正确")
return
}
if money<=||money>account.Balance{
fmt.Println("金额不正确")
return
}
account.Balance-=money
fmt.Println("取款成功")
}
//查询余额
func (account *Account) Query(pwd string){
if pwd!=account.Pwd{
fmt.Println("密码不正确")
return
}
fmt.Printf("你的账号为%v,余额为%v",account.AccountNo,account.Balance)
} func main(){
account:=Account{
AccountNo:"gs111",
Pwd:"",
Balance:100.0, } account.Query("")
account.Deposite(200.0,"")
}

面向对象-封装

model/person.go

package model

import "fmt"

type person struct {
Name string
age int
sal float64
}
//工厂模式,相当于构造函数
func NewPerson(name string) *person{
return &person{
Name:name,
}
} func (p *person) SetAge(age int){
if age>&&age<{
p.age=age
}else{
fmt.Println("年龄范围不正确")
}
}
func (p *person) GetAge() int{
return p.age
}
func (p *person) SetSal(sal float64){
if sal>=&&sal<={
p.sal=sal
}else{
fmt.Println("范围不正确")
}
} func (p *person) GetSal() float64{
return p.sal
}

main/main.go

package main

import (
"fmt"
"oop/11.3.6/model"
) func main(){
p:=model.NewPerson("smith")
p.SetAge()
p.SetSal()
fmt.Println(p)
fmt.Println(p.Name,"age=",p.GetAge(),"sal=",p.GetSal())
}

继承

基础版

package main

import "fmt"

//继承
type Pupil struct{
Name string
Age int
Score int
}
//显示成绩
func (p *Pupil) ShowInfo(){
fmt.Printf("学生名=%v 年龄=%v 成绩=%v\n",p.Name,p.Age,p.Score)
} func (p *Pupil) SetScore(score int){
p.Score=score
} func (p *Pupil) testig(){
fmt.Println("考试中...")
} type Graduate struct {
Name string
Age int
Score int
}
func (p *Graduate) ShowInfo(){
fmt.Printf("学生名=%v,年龄=%v,成绩=%v",p.Name,p.Age,p.Score)
} func (p *Graduate) SetScore(score int){
p.Score=score
} func (p *Graduate) testing(){
fmt.Println("大学生正在考试中。。")
} func main(){
var pupil=&Pupil{
Name: "tom",
Age: ,
}
pupil.testig()
pupil.SetScore()
pupil.ShowInfo()
}

改进版

package main

import (
"fmt"
) //改进版
type Student struct {
Name string
Age int
Score int
}
func (stu *Student) ShowInfo(){
fmt.Printf("学生名=%v,年龄=%v,成绩=%v\n",stu.Name,stu.Age,stu.Score)
}
func (stu *Student) SetScore(score int){
stu.Score=score
} type Pupil struct {
Student//潜入了Student匿名结构体
}
func (p *Pupil) testing(){
fmt.Println("小学生考试中。。。")
} type Graduate struct {
Student
} func (p *Graduate) testing(){
fmt.Println("大学生正在考试中。。。")
} func main(){
pupil:=&Pupil{}
pupil.Student.Name="tom~"
pupil.Student.Age=
pupil.testing()
pupil.Student.SetScore()
pupil.Student.ShowInfo() graduate:=&Graduate{}
graduate.Student.Name="mary~"
graduate.Student.Age=
graduate.testing()
graduate.Student.SetScore()
graduate.Student.ShowInfo() }

a

package main

import (
"fmt"
) type A struct {
Name string
age int
} func (a *A) SayOk(){
fmt.Println("A SayOk",a.Name)
} func (a *A) hello(){
fmt.Println("A hello",a.Name)
} type B struct{
A
}
func main(){
var b B
b.A.Name="tom"
b.A.age=
b.A.hello()
//也可以如下简化
b.Name="smith"
b.age=
b.SayOk()
b.hello()
}

组合

type D struct {
a A
} var d D
d.a.Name="jack"

package main

import "fmt"

type Goods struct{
Name string
Price float64 } type Brand struct{
Name string
Address string }
type TV struct {
Goods
Brand } type TV2 struct {
*Goods
*Brand
} func main(){
tv:=TV{Goods{"电视机001",5000.99},Brand{"海尔","山东"}}
tv2:=TV{
Goods: Goods{
Price:5000.99,
Name:"电视机002",
},
Brand: Brand{
Name:"夏普",
Address:"北京",
},
} fmt.Println("tv",tv)
fmt.Println("tv2",tv2)
tv3:=TV2{&Goods{"电视机003",7000.99},&Brand{"创维","河南"}} tv4:=TV2{&Goods{Name:"电视机004",Price:9000.88},&Brand{Name:"长虹",Address:"四川"}}
fmt.Println("tv3",*tv3.Goods,*tv3.Brand)
fmt.Println("tv4",*tv4.Goods,*tv4.Brand) }

类型作为字段

package main

import "fmt"

type Monster struct {
Name string
Age int
} type E struct{
Monster
int
n int
} func main(){
var e E
e.Name="狐狸精"
e.Age=
e.int=
e.n=
fmt.Println("e=",e)
}
/*
1.一个结构体同类型的匿名字段只能有一个。
2.如果需要多个,则必须给int字段指定名字 */

接口

初识

package main

import "fmt"

//接口

type Usb interface{
Start()
Stop()
} type Phone struct{ } func (p Phone) Start(){
fmt.Println("手机开始工作了")
} func (p Phone) Stop(){
fmt.Println("手机停止工作了")
} type Camera struct { } func (c Camera) Start(){
fmt.Println("相机开始工作。。。")
} func (c Camera) Stop(){
fmt.Println("相机停止工作。。。")
} type Computer struct{ } func (c Computer) Working(usb Usb){
usb.Start()
usb.Stop()
} func main(){
computer:=Computer{}
phone:=Phone{}
camera:=Camera{}
computer.Working(phone)
computer.Working(camera)
}

结构体本身不创建实例,但可以指向一个实现了该接口的自定义类型变量

package main

import "fmt"

//结构体本身不创建实例,但可以指向一个实现了该接口的自定义类型变量
type AInterface interface{
Say()
}
type Stu struct{
Name string
}
func (stu Stu) Say(){
fmt.Println("stu say()")
} func main(){
var stu Stu//结构体变量实现了Say(),实现了AInterface
var a AInterface=stu
a.Say()
}

一个自定义类型可以实现多个接口

package main

import "fmt"

//一个自定义类型可以实现多个接口
type Ainterface interface{
Say()
}
type BInterface interface {
Hello()
} type Monster struct{ }
func (m Monster) Hello(){
fmt.Println("Monster Hello()~~")
}
func (m Monster) Say(){
fmt.Println("Monster Say()~~")
}
func main(){
var monster Monster
var a2 Ainterface=monster
var b2 BInterface=monster
a2.Say()
b2.Hello()
}

接口中不能有变量

实现接口时,继承的接口也必须实现

内置方法排序

package main

import (
"fmt"
"math/rand"
"sort"
) //最佳实践
type Hero struct{
Name string
Age int }
type HeroSlice []Hero func (hs HeroSlice) Len() int{
return len(hs)
} func (hs HeroSlice) Less(i,j int)bool{
return hs[i].Age<hs[j].Age
} func (hs HeroSlice) Swap(i,j int){
hs[i],hs[j]=hs[j],hs[i]
}
type Student struct{
Name string
Age int
Score float64
} func main(){
var intSlice=[]int{,-,,,}
sort.Ints(intSlice)
fmt.Println(intSlice) var heroes HeroSlice
for i:=;i<;i++{
hero:=Hero{
Name: fmt.Sprintf("英雄%d",rand.Intn()),
Age: rand.Intn(),
}
heroes=append(heroes,hero)
}
for _,v:=range heroes{
fmt.Println(v)
} //调用sort
sort.Sort(heroes)
fmt.Println("----排序后----")
for _,v :=range heroes{
fmt.Println(v)
}
i:=
j:=
i,j=j,i
fmt.Println("i=",i,"j=",j)
}

接口实现多态

package main

import "fmt"

//接口体现多态的两种形式,多态参数,多态数组
type Usb interface{
Start()
Stop()
}
type Phone struct {
name string
} func (p Phone) Start(){
fmt.Println("手机开始工作。。。")
} func (p Phone) Stop(){
fmt.Println("手机停止工作")
} type Camera struct {
name string
} func (c Camera) Start(){
fmt.Println("相机开始工作。。。")
} func (c Camera) Stop(){
fmt.Println("相机停止工作...")
} func main(){
var usbArr[]Usb
usbArr[]=Phone{"vivo"}
usbArr[]=Phone{"小米"}
usbArr[]=Phone{"尼康"}
fmt.Println(usbArr)
}

鸭子类型

如果一个动物,走起来像鸭子,叫起来像鸭子,那么它就是鸭子

package main

import "fmt"

//鸭子类型
//定义接口类型
type ISayHello interface {
SayHello() string
} //
type Duck struct {
name string
}
type Person struct {
name string
} func (d Duck) SayHello() string {
return d.name + "叫 ga ga ga"
}
func (p Person) SayHello() string {
return p.name + "说 Hello"
} func main() {
//定义实现接口的对象
duck := Duck{"yaya"}
person := Person{"Steven"}
fmt.Println(duck.SayHello())
fmt.Println(person.SayHello())
fmt.Println("-------")
//定义接口类型的变量
var i ISayHello
i = duck
fmt.Printf("%T,%v,%p \n", i, i, &i)
fmt.Println(i.SayHello())
i = person
fmt.Printf("%T,%v,%p\n", i, i, &i)
fmt.Println(i.SayHello())
}

类型断言

由于接口是一般类型,不知具体类型,就需要使用类型断言

1

package main

import "fmt"

//解决将接口变量赋值给自定义类型的变量
//类型断言
type Point struct {
x int
y int
} func main() {
var a interface{}
var point Point = Point{, }
a = point //实现接口
var b Point
b = a.(Point)//类型断言
fmt.Println(b)
}

2.

package main

import "fmt"

func main(){
var x interface{}
var b2 float32=1.1
x=b2
y:=x.(float32)
fmt.Printf("y的类型是%T,值=%v",y,y)
}

3.类型断言,带检测

package main

import "fmt"

func main(){
var x interface{}
var b2 float32=2.1
x=b2 if y,ok:=x.(float32);ok{
fmt.Println("convert success")
fmt.Printf("type=%T,val=%v",y,y)
}else{
fmt.Println("convert fail")
}
fmt.Println("继续执行。。。") //
}

最佳实践:结构体断言,执行方法

package main

import (
"fmt"
) //类型断言最佳实践1
type Usb interface {
Start()
Stop()
} type Phone struct {
name string
} func (p Phone) Start() {
fmt.Println("手机开始工作。。。")
} func (p Phone) Stop() {
fmt.Println("手机停止。。")
}
func (p Phone) Call() {
fmt.Println("手机 在打电话")
} type Camera struct {
name string
} func (p Camera) Start() {
fmt.Println("相机开始工作。。。")
} func (p Camera) Stop() {
fmt.Println("相机停止。。")
} type Computer struct {
} func (computer Computer) Working(usb Usb) {
usb.Start()
//类型断言,注意体会
if phone, ok := usb.(Phone); ok {
phone.Call()
}
usb.Stop()
} func main() {
var usbArr []Usb
usbArr[] = Phone{"vivo"}
usbArr[] = Phone{"小米"}
usbArr[] = Camera{"尼康"}
//phone 有一个特殊方法,如果是手机需要调用
var computer Computer
for _, v := range usbArr {
computer.Working(v)
fmt.Println()
}
}

类型断言2:

判断输入的参数是什么类型

package main

import "fmt"

//类型断言最佳实践2
//编写一个函数,可以判断输入的参数是什么类型
func TypeJudge(items... interface{}){
for index,x:=range items{
switch x.(type){
case bool:
fmt.Printf("第%v个参数是bool类型,值是%v\n",index,x)
case float32:
fmt.Printf("第%v个参数是float32类型,值是%v\n",index,x)
case float64:
fmt.Printf("第%v个参数是float64类型,值是%v\n",index,x)
case int,int32,int64:
fmt.Printf("第%v个参数是int,int32,int64类型,值是%v\n",index,x)
case string:
fmt.Printf("第%v个参数是string类型,值是%v\n",index,x)
default:
fmt.Printf("第%v个参数是类型 不确定,值是%v\n",index,x)
}
}
} func main(){
var n1 float32=1.1
var n2 float64=2.3
var n3 int32=
var name string="tom"
address:="北京"
n4:=
TypeJudge(n1,n2,n3,name,address,n4)
}

类型断言3

package main

import "fmt"

type Student struct {

}
//类型断言最佳实践2
//编写一个函数,可以判断输入的参数是什么类型
func TypeJudge(items... interface{}){
for index,x:=range items{
switch x.(type){
case bool:
fmt.Printf("第%v个参数是bool类型,值是%v\n",index,x)
case float32:
fmt.Printf("第%v个参数是float32类型,值是%v\n",index,x)
case float64:
fmt.Printf("第%v个参数是float64类型,值是%v\n",index,x)
case int,int32,int64:
fmt.Printf("第%v个参数是int,int32,int64类型,值是%v\n",index,x)
case string:
fmt.Printf("第%v个参数是string类型,值是%v\n",index,x)
case Student:
fmt.Printf("第%v个参数是Student类型,值是%v\n",index,x)
case *Student:
fmt.Printf("第%v个参数是*Student类型,值是%v\n",index,x)
default:
fmt.Printf("第%v个参数是类型 不确定,值是%v\n",index,x)
}
}
} func main(){
var n1 float32=1.1
var n2 float64=2.3
var n3 int32=
var name string="tom"
address:="北京"
n4:=
var s1 Student
var s2 *Student
TypeJudge(n1,n2,n3,name,address,n4,s1,s2)
}

记账案例面向过程

package main
import (
"fmt"
)
func main() {
//声明一个变量,保存接收用户输入的选项
key := ""
//声明一个变量,控制是否退出for
loop := true //定义账户的余额 []
balance := 10000.0
//每次收支的金额
money := 0.0
//每次收支的说明
note := ""
//定义个变量,记录是否有收支的行为
flag := false
//收支的详情使用字符串来记录
//当有收支时,只需要对details 进行拼接处理即可
details := "收支\t账户金额\t收支金额\t说 明"
//显示这个主菜单
for {
fmt.Println("\n-----------------家庭收支记账软件-----------------")
fmt.Println(" 1 收支明细")
fmt.Println(" 2 登记收入")
fmt.Println(" 3 登记支出")
fmt.Println(" 4 退出软件")
fmt.Print("请选择(1-4):")
fmt.Scanln(&key) switch key {
case "":
fmt.Println("-----------------当前收支明细记录-----------------")
if flag {
fmt.Println(details)
} else {
fmt.Println("当前没有收支明细... 来一笔吧!")
} case "":
fmt.Println("本次收入金额:")
fmt.Scanln(&money)
balance += money // 修改账户余额
fmt.Println("本次收入说明:")
fmt.Scanln(&note)
//将这个收入情况,拼接到details变量
//收入 11000 1000 有人发红包
details += fmt.Sprintf("\n收入\t%v\t%v\t%v", balance, money, note)
flag = true case "":
fmt.Println("本次支出金额:")
fmt.Scanln(&money)
//这里需要做一个必要的判断
if money > balance {
fmt.Println("余额的金额不足")
break
}
balance -= money
fmt.Println("本次支出说明:")
fmt.Scanln(&note)
details += fmt.Sprintf("\n支出\t%v\t%v\t%v", balance, money, note)
flag = true
case "":
fmt.Println("你确定要退出吗? y/n")
choice := ""
for { fmt.Scanln(&choice)
if choice == "y" || choice == "n" {
break
}
fmt.Println("你的输入有误,请重新输入 y/n")
} if choice == "y" {
loop = false
}
default :
fmt.Println("请输入正确的选项..")
} if !loop {
break
}
}
fmt.Println("你退出家庭记账软件的使用...")
}

记账案例面向对象

utils/familyAccount.go

package utils
import (
"fmt"
) type FamilyAccount struct {
//声明必须的字段. //声明一个字段,保存接收用户输入的选项
key string
//声明一个字段,控制是否退出for
loop bool
//定义账户的余额 []
balance float64
//每次收支的金额
money float64
//每次收支的说明
note string
//定义个字段,记录是否有收支的行为
flag bool
//收支的详情使用字符串来记录
//当有收支时,只需要对details 进行拼接处理即可
details string
} //编写要给工厂模式的构造方法,返回一个*FamilyAccount实例
func NewFamilyAccount() *FamilyAccount { return &FamilyAccount{
key : "",
loop : true,
balance : 10000.0,
money : 0.0,
note : "",
flag : false,
details : "收支\t账户金额\t收支金额\t说 明",
} } //将显示明细写成一个方法
func (this *FamilyAccount) showDetails() {
fmt.Println("-----------------当前收支明细记录-----------------")
if this.flag {
fmt.Println(this.details)
} else {
fmt.Println("当前没有收支明细... 来一笔吧!")
}
} //将登记收入写成一个方法,和*FamilyAccount绑定
func (this *FamilyAccount) income() { fmt.Println("本次收入金额:")
fmt.Scanln(&this.money)
this.balance += this.money // 修改账户余额
fmt.Println("本次收入说明:")
fmt.Scanln(&this.note)
//将这个收入情况,拼接到details变量
//收入 11000 1000 有人发红包
this.details += fmt.Sprintf("\n收入\t%v\t%v\t%v", this.balance, this.money, this.note)
this.flag = true
} //将登记支出写成一个方法,和*FamilyAccount绑定
func (this *FamilyAccount) pay() {
fmt.Println("本次支出金额:")
fmt.Scanln(&this.money)
//这里需要做一个必要的判断
if this.money > this.balance {
fmt.Println("余额的金额不足")
//break
}
this.balance -= this.money
fmt.Println("本次支出说明:")
fmt.Scanln(&this.note)
this.details += fmt.Sprintf("\n支出\t%v\t%v\t%v", this.balance, this.money, this.note)
this.flag = true
} //将退出系统写成一个方法,和*FamilyAccount绑定
func (this *FamilyAccount) exit() { fmt.Println("你确定要退出吗? y/n")
choice := ""
for { fmt.Scanln(&choice)
if choice == "y" || choice == "n" {
break
}
fmt.Println("你的输入有误,请重新输入 y/n")
} if choice == "y" {
this.loop = false
}
} //给该结构体绑定相应的方法
//显示主菜单
func (this *FamilyAccount) MainMenu() { for {
fmt.Println("\n-----------------家庭收支记账软件-----------------")
fmt.Println(" 1 收支明细")
fmt.Println(" 2 登记收入")
fmt.Println(" 3 登记支出")
fmt.Println(" 4 退出软件")
fmt.Print("请选择(1-4):")
fmt.Scanln(&this.key)
switch this.key {
case "":
this.showDetails()
case "":
this.income()
case "":
this.pay()
case "":
this.exit()
default :
fmt.Println("请输入正确的选项..")
} if !this.loop {
break
} }
}

main/main.go

package main
import (
"go_code/familyaccount/utils"
"fmt"
)
func main() { fmt.Println("这个是面向对象的方式完成~~")
utils.NewFamilyAccount().MainMenu() //思路非常清晰
}

客户管理系统

model/customer.go

package model

import (
"fmt"
) type Customer struct {
Id int
Name string
Gender string
Age int
Phone string
Email string
} //获取一个Customer
func NewCustomer(id int, name string, gender string, age int,
phone string, email string) *Customer {
return &Customer{
Id : id,
Name : name,
Gender : gender,
Age : age,
Phone : phone,
Email : email,
}
} //获取一个Customer, 不提供id
func NewCustomer2(name string, gender string, age int,
phone string, email string) *Customer {
return &Customer{
Name : name,
Gender : gender,
Age : age,
Phone : phone,
Email : email,
}
} //返回Customer的信息
func (this *Customer) GetInfo() string { info := fmt.Sprintf("%v\t%v\t%v\t%v\t%v\t%v", this.Id, this.Name, this.Gender,
this.Age, this.Phone, this.Email)
return info
}

service/customerService.go

package service

import (
_ "fmt"
"go_code/customer/model"
) type CustomerService struct {
//定义一个客户切片,可以存放客户信息
customers []*model.Customer
//定义客户的实际个数
customerNum int
} //先创建一个Customer对象,放到 CustomerService的Customers切片中
//作为测试数据
func NewCustomerService() *CustomerService { customerService := &CustomerService{} //customerService.customers = make([]model.Customer, 1)
customerService.customerNum =
customer := model.NewCustomer(, "张三", "男",
, "", "zs@sohu.com")
customerService.customers = append(customerService.customers, customer) return customerService
} //返回客户的信息数组 func (this *CustomerService) List() []*model.Customer {
return this.customers
} //完成添加客户的功能
func (this *CustomerService) Add(customer *model.Customer) bool { this.customerNum++
//这时我们可以这个customer一个id
customer.Id = this.customerNum
this.customers = append(this.customers, customer) return true } //删除一个客户
func (this *CustomerService) Delete(id int) bool { //先根据id去得到该id的客户对应元素下标
index := this.FindById(id) if index == - {
return false
}
//找到,删除切片对应的index的元素
this.customers = append(this.customers[:index],
this.customers[index+:]...)
//this.customerNum--
return true } //先根据id去得到该id的客户对应元素下标
//如果找到就返回对应的下标,如果找不到,我们返回-1
func (this *CustomerService) FindById(id int) int {
index := -
for i := ; i < this.customerNum; i++ {
if this.customers[i].Id == id {
index = i
break
}
}
return index
}

view/main.go

package main

//引入包
import (
"fmt"
"go_code/customer/service"
"go_code/customer/model"
) type CustomerView struct { //定义一个字段,控制菜单显示是否退出
loop bool
//定义一个字段,接收用户输入
key string
//定义一个CustomerService 字段,主要用于完成对客户信息的各种操作。
customerService *service.CustomerService
} //显示主菜单
// -----------------客户信息管理软件-----------------
//
// 1 添 加 客 户
// 2 修 改 客 户
// 3 删 除 客 户
// 4 客 户 列 表
// 5 退 出
//
// 请选择(1-5):_ func (this *CustomerView) mainMenu() { for { fmt.Println("-----------------客户信息管理软件-----------------")
fmt.Println();
fmt.Println(" 1 添 加 客 户")
fmt.Println(" 2 修 改 客 户")
fmt.Println(" 3 删 除 客 户")
fmt.Println(" 4 客 户 列 表")
fmt.Println(" 5 退 出")
fmt.Print("请选择(1-5):")
fmt.Scanln(&this.key) switch (this.key) {
case "":
this.add()
case "":
//同学们自己加入
case "":
this.delete()
case "":
//调用方法显示客户信息
this.list()
case "":
this.loop = false
default:
fmt.Println("输入错误");
} if !this.loop {
break
} }
} //编写一个方法,可以显示客户信息
// ---------------------------客户列表---------------------------
// 编号 姓名 性别 年龄 电话 邮箱
// 1 张三 男 30 010-56253825 abc@email.com
// 2 李四 女 23 010-56253825 lisi@ibm.com
// 3 王芳 女 26 010-56253825 wang@163.com
// -------------------------客户列表完成------------------------- func (this *CustomerView) list() { //调用 customerService 获取到 客户信息切片
customerList := this.customerService.List() //显示
fmt.Println("---------------------------客户列表---------------------------")
fmt.Println("编号\t姓名\t性别\t年龄\t电话\t邮箱") //遍历
for i := ; i < len(customerList); i++ {
fmt.Println(customerList[i].GetInfo())
}
fmt.Println("---------------------------客户列表完成---------------------------") } //添加客户
// ---------------------添加客户---------------------
// 姓名:张三
// 性别:男
// 年龄:30
// 电话:010-56253825
// 邮箱:zhang@abc.com
// ---------------------添加完成--------------------- func (this *CustomerView) add() { fmt.Println("---------------------添加客户---------------------")
fmt.Println("姓名:")
name := ""
fmt.Scanln(&name)
fmt.Println("性别:")
gender := ""
fmt.Scanln(&gender)
age :=
fmt.Println("年龄:")
fmt.Scanln(&age)
fmt.Println("电话:");
phone := ""
fmt.Scanln(&phone)
fmt.Println("邮箱:");
email := ""
fmt.Scanln(&email) //根据用户输入,创建一个Customer对象
customer := model.NewCustomer2(name, gender, age, phone, email) if(this.customerService.Add(customer)){
fmt.Println("---------------------添加客户成功---------------------");
}else{
fmt.Println("---------------------添加客户失败---------------------");
}
} //删除
// ---------------------删除客户---------------------
// 请选择待删除客户编号(-1退出):1
// 确认是否删除(Y/N):y
// ---------------------删除完成--------------------- func (this *CustomerView) delete() { fmt.Println("---------------------删除客户---------------------")
fmt.Println("请选择待删除客户编号(-1退出)")
id :=
fmt.Scanln(&id)
//如果用户输入-1
if id == - {
return
}
fmt.Println("确认是否删除(Y/N):") choice := ""
fmt.Scanln(&choice) // 可以 if choice == "Y" || choice == "y" { if this.customerService.Delete(id) {
fmt.Println("---------------------删除完成---------------------")
} else {
fmt.Println("---------------------删除失败,id不存在---------------------")
}
}
} func main() { customerView := CustomerView{
loop : true,
}
customerView.customerService = service.NewCustomerService()
customerView.mainMenu()
}

反射

反射的基本介绍
1.反射可以在运行时,动态获取变量各种信息,比如变量的类型(type),类别(kind)
2.如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段,方法)
3.通过反射可以改变变量的值,可以调用关联的方法
4.使用反射需要import("reflect")

1.反射的使用场景

package main

import (
"encoding/json"
"fmt"
) //反射的使用场景
type Monster struct{
Name string `json:"name"`
Age int `json:"age"`
Sal float64 `json:"sal"`
Sex string `json:"sex"`
} func main(){
m:=Monster{
Name: "玉兔精",
Age: ,
Sal: 11663.12,
Sex: "female",
} data,_:=json.Marshal(m) fmt.Println("json result:",string(data))
}

2.演示类型断言

package main

import (
"fmt"
"reflect"
) /*
演示对基本数据类型,interface{},reflect.Value),进行反射的基本操作 */ func reflectTest01(b interface{}){
//通过反射获取传入的变量的type,kind,值
//1.先获取到reflect.TypeOf
rTyp:=reflect.TypeOf(b)
fmt.Println("rType=",rTyp)
//kind为int
//2.获取到refect.Value
rVal:=reflect.ValueOf(b) n2:=+rVal.Int()//转为基础类型int
fmt.Println("n2=",n2)
fmt.Printf("rVal=%v,rVal Type=%T\n",rVal,rTyp)
//下面我们将rVal转成interface{}
iV:=rVal.Interface()
//将interface{}通过断言转成需要的类型
num2:=iV.(int)
fmt.Printf("num2=%v num2 类型=%T\n",num2,num2)
} //专门研究反射[对结构体的反射]
func reflectTest02(b interface{}){
//通过反射传入的变量type,kind,值
//先获取到reflect.Type
rType:=reflect.TypeOf(b)
fmt.Println("rType=",rType)
//2.获取reflect.Value
rVal:=reflect.ValueOf(b)
//下面我们将rVal转成interface{}
iV:=rVal.Interface()
fmt.Printf("iV=%v iv type=%T\n",iV,iV)
//将interface{}通过断言转成需要的类型
//这里,使用带检测的类型断言
stu,ok:=iV.(Student)
if ok{
fmt.Printf("stu.Name=%v\n",stu.Name)
}
}
type Student struct {
Name string
Age int
} func main(){
//var num int=100
//reflectTest01(num)
//2.定义一个student的实例
stu:=Student{
Name:"tom",
Age:,
}
reflectTest02(stu)
}

3.改变传入变量的值

package main

import (
"fmt"
"reflect"
) /*
改变传入变量的值 */
func testInt(b interface{}){
//获取reflect.ValueOf的值
val:=reflect.ValueOf(b)
fmt.Printf("val type=%T\n",val)
//设置值
val.Elem().SetInt()
fmt.Printf("val=%v\n",val)
} func main(){
var num int=
testInt(&num)
fmt.Println("num=",num)
}

4.指针修改变量和反射修改变量对比

package main

import (
"fmt"
"reflect"
) /*
改变传入变量的值 */
//方式一
func update1(str *string) {
//传入指针
fs := reflect.ValueOf(str)
//通过指针修改值
fs.Elem().SetString("jack")
}
//方式二
func update2(str *string) {
//等价于下面的代码
*str = "rose"
}
func main() {
var str string = "tom"
update1(&str)
fmt.Printf("update1()=%v\n", str)
update2(&str)
fmt.Printf("update2()=%v\n", str)
}

5.结构体使用反射获取方法,字段

package main

import (
"fmt"
"reflect"
) /*
使用反射来遍历结构体字段,调整结构体的方法,并获取结构体标签的值 */
//
type Monster struct {
Name string `json:"name"`
Age int `json:"age"`
Score float32 `json:"score"`
Sex string
} //返回两个数的和
func (s Monster) GetSum(n1, n2 int) int {
return n1 + n2
} //接收四个值,给s赋值
func (s Monster) Set(name string, age int, score float32, sex string) {
s.Name = name
s.Age = age
s.Score = score
s.Sex = sex
} //显示s值
func (s Monster) Print() {
fmt.Println("---start---")
fmt.Println(s)
fmt.Println("---end---")
} func TestStruct(a interface{}) {
//获取reflect.Type类型
typ := reflect.TypeOf(a)
//获取reflect.Value
val := reflect.ValueOf(a)
//获取到a对应的类别
kd := val.Kind()
fmt.Printf("kind type=%T,kd=%v\n",kd,kd)//结构类别
fmt.Printf("a type=%T,a=%v\n",a,a)//具体定义类型
fmt.Printf("%v\n",reflect.Struct)
//如果传入的不是struct,就退出
if kd != reflect.Struct {
fmt.Println("expect struct")
return
}
//获取该结构体有几个字段
num := val.NumField()
fmt.Printf("struct has %d fields\n", num) //4
//遍历结构体所有字段
for i := ; i < num; i++ {
fmt.Printf("Field %d:值为=%v\n", i,val.Field(i))
//获取到结构体的标签,注意前面通过reflect.Type来获取tag标签的值
tagVal := typ.Field(i).Tag.Get("json")
//如果该字段于tag标签就显示,否则就不显示
if tagVal != "" {
fmt.Printf("Field %d:tag为=%v\n", i, tagVal)
}
}
//获取该结构体有多少个方法
numOfMethod := val.NumMethod()
fmt.Printf("struct has %d methods\n", numOfMethod)
//var params []reflect.Value
//方法的排序默认是按照函数名的排序(ASCII码)
val.Method().Call(nil) //获取到第三个方法调用它
//调用结构体的第一个方法 Method(0)
var params []reflect.Value //声明了 []reflect.Value
params = append(params, reflect.ValueOf())
params = append(params, reflect.ValueOf())
res := val.Method().Call(params) //传入的参数是 []reflect.Value 返回[] reflect.Value
fmt.Println("res=", res[].Int()) //返回结果是[]reflect.Value } func main() {
var a Monster = Monster{
Name: "黄鼠狼精",
Age: ,
Score: 30.8,
}
TestStruct(a)
}

6.

7.

8.

9.

。。。。

go 面向对象的更多相关文章

  1. angular2系列教程(六)两种pipe:函数式编程与面向对象编程

    今天,我们要讲的是angualr2的pipe这个知识点. 例子

  2. 一起学 Java(二)面向对象

    一.方法函数 函数也称为方法,就是定义在类中的具有特定功能的一段独立代码.用于定义功能,提高代码的复用性. 函数的特点1> 定义函数可以将功能代码进行封装,便于对该功能进行复用:2> 函数 ...

  3. js面向对象学习 - 对象概念及创建对象

    原文地址:js面向对象学习笔记 一.对象概念 对象是什么?对象是“无序属性的集合,其属性可以包括基本值,对象或者函数”.也就是一组名值对的无序集合. 对象的特性(不可直接访问),也就是属性包含两种,数 ...

  4. 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型

    前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...

  5. .NET 基础 一步步 一幕幕[面向对象之对象和类]

    对象和类 本篇正式进入面向对象的知识点简述: 何为对象,佛曰:一花一世界,一木一浮生,一草一天堂,一叶一如来,一砂一极乐,一方一净土,一笑一尘缘,一念一清静.可见"万物皆对象". ...

  6. 简单分析JavaScript中的面向对象

    初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...

  7. Java程序员应该了解的10个面向对象设计原则

    面向对象设计原则: 是OOPS(Object-Oriented Programming System,面向对象的程序设计系统)编程的核心,但大多数Java程序员追逐像Singleton.Decorat ...

  8. JavaScript学习笔记(三)——this、原型、javascript面向对象

    一.this 在JavaScript中this表示:谁调用它,this就是谁. JavaScript是由对象组成的,一切皆为对象,万物皆为对象.this是一个动态的对象,根据调用的对象不同而发生变化, ...

  9. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  10. .NET基础拾遗(2)面向对象的实现和异常的处理基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理基础 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开 ...

随机推荐

  1. 爬虫之 cookie , 验证码,模拟登陆,线程

    需求文档的定制 糗事百科的段子内容和作者(xpath的管道符)名称进行爬取,然后存储到mysql中or文本 http://sc.chinaz.com/jianli/free.html爬取简历模板 HT ...

  2. SpringCloud与微服务Ⅸ --- Zuul路由网关

    一.Zool是什么 Zuul包含了对请求路由和过滤两个最主要的功能: 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础而过滤器功能则负责对请求的处理过程进行干预,是实现 ...

  3. JAVA String对象和字符串常量的关系解析

    JAVA String对象和字符串常量的关系解析 1 字符串内部列表 JAVA中所有的对象都存放在堆里面,包括String对象.字符串常量保存在JAVA的.class文件的常量池中,在编译期就确定好了 ...

  4. js笔记(1)--第一天记录

    刚刚接触JavaScript这门语言不久,所以希望每一次都记一点东西下来,巩固下知识. 首先,写了一个demo,是来计算两个数字的和的,如果直接把 v1=text1.value,和 v2=text2. ...

  5. 使用Java封装一个DBUtils类(反射)

    刚开始学JavaWeb时,我是调用N个setter方法将从数据库中查询出的数据封装成JavaBean的,极其繁琐. 后来了解SpringJDBC后,发现它提供的接口非常简单,然后就想自己封装一个简单的 ...

  6. Java.work7 访问权限、对象使用作业20194651

    题目1: 在作业5的基础上,再创建一个柱体类,包含矩形对象.高和体积等三个成员变量,一个构造方法进行成员变量初始化,和计算体积.换底两个功能方法,在主类中输入长.宽.高,计算柱体体积,输入新的长.宽. ...

  7. Windows虚拟器的安装与使用

    前言 先说:你们要的东西我会放在文中和文章末尾,拿文件记得点赞,一手交钱一手交货 马上初中朋友们就要开始上网课了哎!(博主也是一位初中生) 有人可能会受网课的影响而不能……, 所以各路神仙研究出了各种 ...

  8. [兴趣使然]用python在命令行下画jandan像素超载鸡

    下午刷煎蛋的时候看到 Dthalo 蛋友发的系列像素超载鸡,就想自己试试用python脚本画一个,老男孩视频里的作业真没兴趣,弄不好吧没意思,往好了写,自己控制不好,能力不够. 所以还是找自己有兴趣的 ...

  9. 【Java并发工具类】CountDownLatch和CyclicBarrier

    前言 下面介绍协调让多线程步调一致的两个工具类:CountDownLatch和CyclicBarrier. CountDownLatch和CyclicBarrier的用途介绍 CountDownLat ...

  10. vue 过渡 & 动画

    过渡 & 动画 过渡动画 用css先定义好动画效果 .a-enter-active, .a-leave-active { transition: all 1.5s; } .a-enter, . ...