本demo使用golang+iris+gorm模拟一个简单的后端MVC模式开发
iristest
├─common
│ ├─date
│ ├─db
│ │ ├─gormDb
│ │ └─xormDb
│ ├─encryption
│ ├─file
│ │ └─image
│ ├─log
│ ├─redis
│ ├─request
│ ├─res
│ └─token
├─config
├─controller
│ ├─loginController
│ └─userInfoController
├─dao
│ ├─userDao
│ └─userDao2
├─do
│ └─user
├─main
├─route
└─service
├─loginService
└─userInfoService
golang有着自己的优势点,相比c/c++,它有着庞大的开源库(github),相比java它有自己的性能优势.
从golang语法层面上来说,它舍弃了三目运算符,函数重载,默认参数等一系列语法花架子,作者的初衷是为了使得语法得到统一,简单来说,就是完成一个功能只有一种写法,这样方便其他人更好的阅读和扩展,也体现了golang代码严谨性
相信很多刚用go的人都会吐槽go的封装语法(首字母大小写) 它使得自定义不再是单纯的自定义,再加上golang独特的语法,它好像就是故意使自己与从不同.
golang新增的语法
从这些语法层面来看,它好像特别适合用来造轮子,但是不同与c++的是,它很多功能都已经具备了,而不需要从零开始.
我们只需要在它已有的功能基础上,把这些功能封装成我们自己方便使用的东西
golang的框架大同小异,因为它语言特性的原因,使得它的框架通常都是一个结构体或者一个package实现了所有的方法,而使用它的方式也是拿到这个结构体的指针,在代码中进行传递和调用
java中以类为单位,每个public类名都必须与自己的源文件名一致,不同类无法直接访问另一个类的私有成员
golang中以包为单位,一个文件夹为一个包,在这个文件夹下所有的go文件都属于这个包,相同包之间可互相访问私有成员
java中设置公有私有需要关键字public,private
golang中设置公有私有需要看首字母是否大写
java中是以面向对象思维写代码,关于一个类型的所有,都写在一个class里
golang既可以实现面向对象,也可以使用面向过程,在于项目的复杂程度而让程序员怎样去倾斜它
java中允许使用函数重载,同一个类下可以使用相同名的函数实现对不同参数的处理
public Class User{
public int get(int i){
return i;
}
public String get(String s){
return s;
}
//允许
}
golang中不允许对函数重载,同一个包下想要实现对不同的参数处理就必须使用不同的函数名(不同包或者不同结构体函数可以同名)
package user
func Get(i int) int{
return i
}
func Get(s string) string{
return s
}
//编译器报错 'Get' redeclared in this package
func Get(i int)int{
return i
}
type User struct{}
func (u *User) Get(i int)int{
return i
}
//允许
java中基本类型是值传递,引用类型是引用传递,java中的引用类型有类,接口,数组
golang中所有传递都是值传递,三种特殊引用类型有map,切片,channel,他们的传递在底层实际上被封装成包含指针的结构体传递,使用指针可以使任意类型进行指针传递
//当我们把切片进行传递的时候,实际上是传递了一个Slice结构体过去
//当我们没有向切片追加数据使,结构体内指针指向的是同一个数组,当向切片内追加数据后触发扩容机制生成新的数组
//函数内的结构体内部指针指向新的数组,原来的Slice结构内指针依旧指向原数组
func main() {
ss := []string{"a", "b", "c"}
fmt.Println(ss) //a,b,c
update(ss)
fmt.Println(ss) //xx,b,c
add(ss)
fmt.Println(ss) //xx,b,c
}
func update(slice []string) {
slice[0] = "xx"
}
func add(slice []string) {
slice = append(slice, "yy")
}
//golang中map实际上是指向底层hmap结构的一个指针,所以传递时实际上把hmap结构体的指针传递过去
//在函数内部操作的实际上是同一个map
//指针位置并没有改变,所以map触发扩容后依旧指向的是原hmap内部指针指向的位置
func main() {
ss := map[string]string{
"name": "hello",
"age": "18",
}
//注意,map内部key是无序的
fmt.Println(ss) //name:hello,age:18
update(ss)
fmt.Println(ss) //name:zhangsan,age:18
add(ss)
fmt.Println(ss) //name:zhangsan,age:18,new1:123,new2:456
}
func update(mp map[string]string) {
mp["name"] = "zhangsan"
}
func add(mp map[string]string) {
mp["new1"] = "123"
mp["new2"] = "456"
}
//channel是一个特殊的引用类型,它返回的是一个指向hchan的指针,所以在函数内操作的是同一个channel
java中使用try catch处理异常
try{
int i = Integer.parseInt("1234");
}catch(Exception ex){
//异常了
ex.printStackTrace();
}finally {
//不管异不异常都会执行
}
golang中的异常处理
i, err := strconv.Atoi("1234")
if err != nil{
//异常了
log.Fatalln(err.Error())
}
//golang中有一个段子,就是程序员大部分时间都在if err != nil
java开启多线程需要继承Thread类,或者实现Runnable或Callable接口
golang中只需要一个关键字go
go func(){
//xxxxxx
}()
java中使用String类下的substring方法
String s = "abc123abc".substring(3,6)
// 123
golang中利用切片(字符串=字符数组)
s := "abc123abc"[3:6]
//123
java中使用new关键字为对象申请内存
User user = new User();
golang中使用make为slice,map,和channel申请空间,使用new为其他引用类型申请空间
//切片申请空间时需要使用第二个参数来作为初始化
slicss := make([]int,5)
//[0,0,0,0,0]
//注意,此时向切片内加入元素不会覆盖初始化的内容
slicss = append(slicss, 5)
//[0,0,0,0,0,5]
//map申请空间可以不用第二个参数
mp := make(map[string]any)
mp["name"] = "zhangsan"
mp["age"] = 18
c := make(chan int)
go func(){
c <- 666
}()
n := <- c
java中不允许有多个返回值
golang中可以有多个返回值,接受的时候必须用同样多的参数接受,不需要的值可以用_丢弃
func f()(string,bool,int){
return "zhangsan",true,18
}
name,sex,age := f();
golang中可以给返回值定义变量名,给这个变量赋值后,不需要在return后面写返回值
func f()(rs string){
rs = "hello"
return
}
java中无法直接将函数作为参数进行传递
golang中函数也时一种引用类型,可作为参数进行传递
func ff(f func()){
f()
}
ff(func(){
fmt.Println("hello world")
})
//带参带返回值的函数,函数作为参数时,调用者无法获取该函数的参数,所以需要额外把参数进行传递
func ff(str1 string,i int,f func(string,string)bool)bool{
str2 := strconv.Itoa(i)
return f(str1,str2)
}
//假如此时有个函数
func f1(str1 string,i int)bool{
//xxxxxxxxxx业务代码
return false
}
//当函数参数和返回值不匹配时无法作为参数,但是我们可以用另一个函数包装它
func f2(f func(string,int)bool)func(string,string)bool{
return func(s1 string,s2 string)bool{
i,_ := strconv.Atoi(s2)
return f1(str1,i)
}
}
//此时ff接收通过f2传递的f1
ff("zhangsan",18,f2(f1))
golang中只要实现了接口中的方法,我们就说它实现了这个接口,它更多的是被当成一种类型来进行通信和对代码进行隔离
type IUser interface{
GetName()string
}
func Name(user IUser)string{
return user.GetName()
}
//xxxxxxxxxxxxxxxxxxxxxxxxxx
type User1 struct{
name string
age int
}
func NewUser1(name string,age int)*User1{
return &User1{
name:name,
age:age,
}
}
func (u *User1)GetName()string{
return u.name
}
func main(){
u1 := NewUser1("张三",18)
name := Name(u1)
fmt.Println(name)
}
golang中没有明确提供继承的方式,但是它可以使用内部匿名结构体简单的实现继承
type person struct{}
func (p *person)Print()string{
return "hello"
}
type user struct{
person
username string
}
func main(){
u := &user{}
fmt.Println(u.Print())
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。