- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
代码简单演示:
package main
import "fmt"
//main方法调用前会被调用
func init() {
fmt.Println("init方法会在main方法调用前会被调用")
}
//声明全局变量 方法一,二,三是可以的,但是方法四不行
var g1 int
var g2 int =520
var g3 =521
//方法四声明全局变量会报错
//:=只能用在函数体内使用
//g4:=1000
func main() {
fmt.Println("=============================")
fmt.Println("方法一:声明一个变量,默认值为0")
var a int
//Println是换行输出
fmt.Println("a= ", a)
//Printf是格式化输出--需要手动换行
fmt.Printf("type of a= %T \n", a)
fmt.Println("=============================")
fmt.Println("方法二: 声明一个变量,初始化一个值")
var b int = 100
fmt.Println("b= ", b)
fmt.Printf("type of b= %T \n", b)
fmt.Println("=============================")
fmt.Println("方法二: 声明一个变量,初始化一个值")
var s string = "大忽悠";
fmt.Printf("type of s= %T\n", s)
fmt.Println("=============================")
fmt.Println("方法三:在初始化的时候,省略数据类型,通过值自动匹配当前的变量的数据类型")
var c = 100
fmt.Println("c= ", c)
fmt.Printf("type of c= %T \n", c)
fmt.Println("=============================")
fmt.Println("方法四: 省去var关键字,直接自动匹配")
e := "哈哈哈哈"
fmt.Println("e =",e)
fmt.Printf("type of e= %T\n",e)
fmt.Println("=============================")
fmt.Println("方法四: 省去var关键字,直接自动匹配")
f := 3.14
fmt.Println("f =",f)
fmt.Printf("type of f= %T\n",f)
fmt.Println("=============================")
fmt.Println("全局变量输出测试: g1=",g1," g2=",g2," g3=",g3)
fmt.Println("=============================")
//声明多个变量
var xx,yy int =100,200
fmt.Println("同时声明多个类型相同的变量: xx=",xx," yy=",yy)
var kk,ll=300,"呜呜呜"
fmt.Println("同时声明多个类型不同的变量: kk=",kk," ll=",ll)
fmt.Println("=============================")
fmt.Println("多行的变量声明测试: ")
var (
aa int =100
bb bool=true
)
fmt.Println("aa= ",aa," bb=",bb)
}
输出结果:
init方法会在main方法调用前会被调用
=============================
方法一:声明一个变量,默认值为0
a= 0
type of a= int
=============================
方法二: 声明一个变量,初始化一个值
b= 100
type of b= int
=============================
方法二: 声明一个变量,初始化一个值
type of s= string
=============================
方法三:在初始化的时候,省略数据类型,通过值自动匹配当前的变量的数据类型
c= 100
type of c= int
=============================
方法四: 省去var关键字,直接自动匹配
e = 哈哈哈哈
type of e= string
=============================
方法四: 省去var关键字,直接自动匹配
f = 3.14
type of f= float64
=============================
全局变量输出测试: g1= 0 g2= 520 g3= 521
=============================
同时声明多个类型相同的变量: xx= 100 yy= 200
同时声明多个类型不同的变量: kk= 300 ll= 呜呜呜
=============================
多行的变量声明测试:
aa= 100 bb= true
package main
import "fmt"
//const定义枚举类型
const(
SUCCESS=200
NOT_FOUND=404
ERROR=500
)
const(
//可以在const()添加一个关键字iota,每行的iota都会增加1,第一行的iota默认为0
ZERO=iota //iota=0
FIRST //iota=1
SECOND //iota=2
THREE //iota=3
)
const (
a,b =iota+1,iota+2 //iota=0,a=iota+1,b=iota+2,a=1,b=2
c,d //iota=1,c=iota+1,d=iota+2,c=2,d=3
e,f //iota=2,e=iota+1,f=iota+2,e=3,f=4
g,h =iota*2,iota*3 //iota=3,g=iota*2,h=iota*3,g=6,h=9
i,k //iota=4,i=iota*2,k=iota*3 ,i=8,k=12
)
func main() {
//常量---只读
const len int =10;
fmt.Println("len= ",len)
fmt.Println("SUCCESS: ",SUCCESS)
fmt.Println("NOT_FOUND: ",NOT_FOUND)
fmt.Println("ERROR: ",ERROR)
fmt.Println("a= ",a," b= ",b)
fmt.Println("c= ",c," d= ",d)
fmt.Println("e= ",e," f= ",f)
fmt.Println("g= ",g," h= ",h)
fmt.Println("i= ",i," k= ",k)
//iota只能够配合const()一起使用,iota在const()才有累加效果
//var temp int=iota;
}
package main
import "fmt"
//函数返回一个值
func foo1(a string,b int) int{
fmt.Println("a= ",a)
fmt.Println("b= ",b)
c:=100
return c
}
//返回多个值,匿名的
func fool2(a string)(int,int){
fmt.Println("a= ",a)
return 666,777
}
//返回多个值,有形参名称的
func fool3(a string)(r1 string, r2 int){
fmt.Println("a= ",a)
//给有名称的返回值变量赋值
r1="大忽悠"
r2=100
return
}
func fool4(a string)(r1,r2 int){
fmt.Println("a= ",a)
//对于形参a和返回值变量r1,r2来说,他们的生命周期被局限在当前方法体内
//但是对于返回值变量r1和r2来说,如果不进行赋值,默认为0
fmt.Println("r1= ",r1," r2= ",r2)
//给有名称的返回值变量赋值
r1=520
r2=100
return
}
func main() {
fmt.Println("foo1函数返回一个值: ",foo1("大 fu you",100))
fmt.Println("----------------------------------------------")
ret1,ret2:=fool2("哈哈哈2")
fmt.Println("fool2函数有多个返回值,ret1= ",ret1," ret2= ",ret2)
fmt.Println("----------------------------------------------")
ret3,ret4:=fool3("哈哈哈3")
fmt.Println("fool3函数有多个返回值,ret3= ",ret3," ret4= ",ret4)
fmt.Println("----------------------------------------------")
ret5,ret6:=fool4("哈哈哈4")
fmt.Println("fool4函数有多个返回值,ret5= ",ret5," ret6= ",ret6)
fmt.Println("----------------------------------------------")
}
导包测试:
package handle
import "fmt"
func init() {
fmt.Println("afterHandle执行初始化逻辑")
}
func AfterHandle(){
fmt.Println("方法执行后的拦截逻辑.....")
}
package handle
import "fmt"
func init() {
fmt.Println("beforeHandle执行初始化逻辑")
}
func BeforeHandle() {
fmt.Println("方法执行前的拦截逻辑.....")
}
导入handle包:
package main
import (
"fmt"
"handle"
)
func main() {
handle.BeforeHandle()
fmt.Println("哈哈哈哈")
handle.AfterHandle()
}
结果:
package handle
import "fmt"
func init() {
fmt.Println("beforeHandle执行初始化逻辑")
}
//当前函数名大写,表示当前函数对外开放,别的包只要导入了该包,便可以调用这个函数
//如果当前函数名小写,表示当前函数只能在当前包内被调用
func BeforeHandle() {
fmt.Println("方法执行前的拦截逻辑.....")
}
匿名导入:
package main
import (
"fmt"
_"handle"
)
func main() {
fmt.Println("哈哈哈哈")
}
别名导入:
package main
import (
"fmt"
myhandle "handle"
)
func main() {
myhandle.BeforeHandle()
fmt.Println("哈哈哈哈")
myhandle.AfterHandle()
}
全部导入本包: 这种方法在多个包的情况下容易产生方法名冲突的问题
package main
import (
"fmt"
. "handle"
)
func main() {
BeforeHandle()
fmt.Println("哈哈哈哈")
AfterHandle()
}
defer关键字的功能类似于c++的析构函数,用defer关键字声明的函数,会在当前方法执行结束后被执行,并且执行顺序类似于栈的先进后出关系
先声明的方法defer方法先入栈,因此后执行
package main
import "fmt"
func func1() {
fmt.Println("A")
}
func func2() {
fmt.Println("B")
}
func func3() {
fmt.Println("C")
}
func main(){
defer func1()
fmt.Println("hhh")
defer func2()
defer func3()
}
当defer和return同时出现,return先执行,defer后执行
package main
import "fmt"
func func1() {
fmt.Println("A")
}
func func2() int{
fmt.Println("B")
return 0;
}
func func3() int {
fmt.Println("C")
defer func1()
return func2();
}
func main(){
func3()
}
package main
import "fmt"
//只能接受长度为8的固定数组
//在go语言中,所有的变量都是值传递
func printArr(arr [8]int){
arr[0]=520
fmt.Println("函数中输出传入后修改的数组: ")
for index, val := range arr {
fmt.Println("index: ",index," val: ",val)
}
}
func main() {
//固定长度的数组
var arr1 [10]int;
fmt.Println("打印输出arr1数组: ");
for i:=0; i<len(arr1) ;i++ {
fmt.Print(arr1[i]," ")
}
fmt.Println()
fmt.Println("--------------------------------------------")
arr2:=[8]int{1,2,3,4,5}
//下面arr2的输出,也可以验证这里是数组值传递
printArr(arr2)
for index, val := range arr2 {
fmt.Println("当前遍历索引为: ",index," 当前索引对应的值为: ",val)
}
fmt.Println("查看数组的类型:")
fmt.Printf("arr1数组的类型为: %T\n",arr1)
fmt.Printf("arr2数组的类型为: %T\n",arr2)
}
//这里拿到的是数组的指针
func printArr(arr []int){
arr[0]=520
fmt.Println("函数中输出传入后修改的数组: ")
for index, val := range arr {
fmt.Println("index: ",index," val: ",val)
}
}
func main() {
//动态数组---切片---slice
arr2:=[]int{1,2,3,4,5}
//动态数组就是执行这块数组内存的一个指针引用
//因此这里函数传递的是指向这块内存的一个指针引用
printArr(arr2)
for index, val := range arr2 {
fmt.Println("当前遍历索引为: ",index," 当前索引对应的值为: ",val)
}
}
动态数组在传参上是引⽤传递,⽽且不同元素⻓度的动态数组他们的形参是⼀致。
package main
import "fmt"
func main() {
fmt.Println("声明slcie1是一个切片,并且初始化,默认值为1,2,3 长度为3: ")
slice1 := []int{1,2,3}
fmt.Println(slice1)
fmt.Println("----------------------------")
fmt.Println("声明slice2是一个切片,但是并没有给slice分配空间")
var slice2 []int;
fmt.Println(slice2)
fmt.Println("----------------------------")
fmt.Println("给slice2开辟三个空间,默认值为0: ")
slice2=make([]int,3)
fmt.Println(slice2)
fmt.Println("----------------------------")
fmt.Println("声明slice3是一个切片,同时给slice3分配三个空间,默认值为0")
var slice3 []int=make([]int,3);
fmt.Println(slice3)
fmt.Println("----------------------------")
fmt.Println("声明slice4是一个切片,同时给slice4分配空间,3个空间,通过:=推导出slice4是一个切片")
slice4:=make([]int,3)
slice4[0]=1
slice4[1]=2
slice4[2]=3
fmt.Println(slice4)
fmt.Println("----------------------------")
fmt.Println("输出slice4切片的长度和详细信息(-v): ")
fmt.Printf("len= %d,slice= %v\n",len(slice4),slice4)
fmt.Println("----------------------------")
fmt.Println("判断一个slice是否为0")
if slice3 == nil{
fmt.Println("slice3是一个空切片")
}else {
fmt.Println("slice3是有空间的")
}
var slice5 []int;
if slice5 == nil{
fmt.Println("slice5是一个空切片")
}else {
fmt.Println("slice5是有空间的")
}
}
package main
import "fmt"
func main() {
//最后一个参数指定的是切片容量
var nums=make([]int,3,5)
fmt.Printf("切片长度= %d, 切片容量为= %d, 切片详细信息=%v \n",len(nums),cap(nums),nums)
}
len和cap有啥区别呢?—>看图
func main() {
//最后一个参数指定的是切片容量
var nums=make([]int,3,5)
info(nums)
fmt.Println("向nums切片追加一个元素1")
nums=append(nums,1,2)
info(nums)
}
func info(nums []int){
fmt.Printf("切片长度= %d, 切片容量为= %d, 切片详细信息=%v \n",len(nums),cap(nums),nums)
}
如果此时在追加一条数据呢?
显然会扩容,每次扩容为当前cap两倍的大小
package main
import "fmt"
func main() {
//创建切片
nums:=[]int{1,2,3,4,5,6,7}
info(nums)
//切片截取---联想JAVA中String的subString功能
info(nums[1:4])
//默认下限为0
info(nums[:3])
//模式上限为len(s)
info(nums[4:])
}
func info(nums []int){
fmt.Printf("切片长度= %d, 切片容量为= %d, 切片详细信息=%v \n",len(nums),cap(nums),nums)
}
截取只是利用指针实现了逻辑上的分离,物理上还是一块内存,因此对截取后某部分的数据进行操作,会影响原切片
package main
import "fmt"
func main() {
//创建切片
nums:=[]int{1,2,3,4,5,6,7}
info(nums)
nums1:=nums[1:4]
nums1[0]=520
info(nums)
info(nums1)
}
func info(nums []int){
fmt.Printf("切片长度= %d, 切片容量为= %d, 切片详细信息=%v \n",len(nums),cap(nums),nums)
}
package main
import "fmt"
func main() {
//创建切片
nums:=[]int{1,2,3,4,5,6,7}
info(nums)
s2:=make([]int,3)
copy(s2,nums)
info(s2)
s2[0]=520
info(nums)
info(s2)
}
func info(nums []int){
fmt.Printf("切片长度= %d, 切片容量为= %d, 切片详细信息=%v \n",len(nums),cap(nums),nums)
}
可以看出copy函数是深拷贝的实现
package main
import (
"fmt"
)
func main() {
//声明一个map类型,key是String,val是String
var myMap1 map[string]string
if 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)
fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
//第二种声明方式
myMap2:=make(map[int]string);
myMap2[0]="123"
myMap2[1]="321"
fmt.Println(myMap2)
fmt.Println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>")
//第三种声明方式
myMap3:=map[int]string{
1 :"dhy",
2 :"ddhy",
}
fmt.Println(myMap3)
}
package main
import "fmt"
//这里传递的是map的引用
func printMap(map1 map[string]string){
//遍历元素
for key, val := range map1 {
fmt.Print(" key= ",key)
fmt.Print(" val= ",val)
fmt.Println()
}
fmt.Println("-------------------")
}
func main() {
map1:=make(map[string]string)
//添加元素
map1["China"]="BeiJing"
map1["Japan"]="Tokyo"
map1["USA"]="NewYork"
printMap(map1)
//删除元素
delete(map1,"China")
printMap(map1)
//修改元素
map1["USA"]="DC"
printMap(map1)
}
package main
import "fmt"
//声明一种行的数据类型myint,是int的一个别名
type myint int
//定义一个结构体
type Book struct {
title string
auth string
}
//值传递
func changeBook(book Book){
book.auth="大忽悠";
}
//地址传递
func changeBook1(book *Book){
book.auth="大忽悠";
}
func main() {
var tempVal myint=100
fmt.Println("tempVal=",tempVal)
fmt.Println("--------------------")
var book Book
book.title="Go语言圣经"
book.auth="不知道"
fmt.Printf("%v\n",book)
fmt.Println("--------------------")
//值传递
changeBook(book)
fmt.Printf("%v\n",book)
fmt.Println("--------------------")
//地址传递
changeBook1(&book)
fmt.Printf("%v\n",book)
fmt.Println("--------------------")
}
package main
import "fmt"
//声明一种行的数据类型myint,是int的一个别名
type myint int
//定义一个结构体
//类名首字母大写,表示该属性对外可以访问,否则只能当前包类访问
type Book struct {
title string
auth string
}
//这里方法名首字母大小写同上
func (this Book) getTitle() string{
return this.title
}
//值传递---this Book
func (this Book) setTitle(title string){
//这里调用该方法对象的一个副本---拷贝
this.title=title
}
//引用传递
func (this *Book) setTitle1(title string){
this.title=title
}
func (this Book) show() {
fmt.Println("书名: ",this.title," 作者: ",this.auth)
}
func main() {
book:=Book{title:"大忽悠历险记",auth:"大忽悠"}
book.show()
fmt.Println("值传递演示: ")
book.setTitle("小朋友历险记")
book.show()
fmt.Println("引用传递演示: ")
book.setTitle1("小朋友历险记")
book.show()
}
类名、属性名、⽅法名 ⾸字⺟⼤写表示对外(其他包)可以访问,否则只能够在本包内访问
package main
import "fmt"
type Huamn struct {
name string
sex string
}
func (this *Huamn) Eat(){
fmt.Println("Huamn.Eat()...")
}
func (this *Huamn) Walk(){
fmt.Println("Huamn.Walk()...")
}
///
type SuperMan struct {
Huamn //SuperMan类继承了HUMAN类的方法和属性
level int
}
//重写了父类的方法
func (this *SuperMan) Eat(){
fmt.Println("SuperMan.Eat()...")
}
func (this *SuperMan) Play(){
fmt.Println("SuperMan.Play()...")
}
func (this SuperMan) Show(){
fmt.Println("姓名: ",this.name," 性别: ",this.sex," 等级: ",this.level)
}
func main() {
huamn:= Huamn{name: "大忽悠", sex: "未知"}
huamn.Eat()
huamn.Walk()
//定义一个子类对象
superMan:= SuperMan{Huamn{name: "小朋友", sex: "未知"}, 1000}
superMan.Show()
//方式二:
var s SuperMan
s.level=520
s.name="大忽悠"
s.sex="MAN"
s.Show()
}
Go语言对烦人的权限做了删减,继承过程中没有啥子私有,公开,保护权限,只在是否对其他包公开这里做了权限限制,而且这一点是通过大小写完成的
基本要素:
//本质是一个指针
type Animal interface {
Sleep()
GetColor() string
GetType() string
}
type Cat struct {
color string
}
func (this *Cat) Sleep(){
fmt.Println("Cat is Sleep")
}
func (this *Cat) GetColor() string{
return this.color
}
func (this *Cat) GetType() string{
return "Cat"
}
type Dog struct {
color string
}
func (this *Dog) Sleep(){
fmt.Println("Dog is Sleep")
}
func (this *Dog) GetColor() string{
return this.color
}
func (this *Dog) GetType() string{
return "Dog"
}
package main
import (
"fmt"
)
//本质是一个指针
type Animal interface {
Sleep()
GetColor() string
GetType() string
}
type Cat struct {
color string
}
func (this *Cat) Sleep(){
fmt.Println("Cat is Sleep")
}
func (this *Cat) GetColor() string{
return this.color
}
func (this *Cat) GetType() string{
return "Cat"
}
type Dog struct {
color string
}
func (this *Dog) Sleep(){
fmt.Println("Dog is Sleep")
}
func (this *Dog) GetColor() string{
return this.color
}
func (this *Dog) GetType() string{
return "Dog"
}
func test(animal Animal){
animal.Sleep()
color := animal.GetColor()
getType := animal.GetType()
fmt.Println("动物的颜色: ",color," 类型为: ",getType)
}
func main() {
//接口的数据类型,父类指针
var animal Animal
animal=&Cat{"BLACK"}
test(animal)
animal=&Dog{"BROWN"}
test(animal)
}
package main
import "fmt"
//interface{}是万能类型
func myFunc(arg interface{}){
fmt.Println("myFunc is called...")
fmt.Println(arg)
//interface{}该如何区分,此时引用的底层数据类型到底是什么
//给interface{}提供"类型断言"的机制
//返回的第二个参数是一个bool,表示当前断言的结果,第一个参数就是值
val, ok := arg.(Book1)
if !ok{
fmt.Println("arg is not Book1 type")
}else{
fmt.Println("arg is Book1 type,val= ",val)
fmt.Printf("value type is %T\n",val)
}
}
type Book1 struct {
auth string
}
func main() {
book := Book1{auth: "哈哈哈哈"}
myFunc(book)
}
这里空接口类型指针,可以指向任何数据类型,因此可以看做是元数据类型,即所有数据类型都会实现的类型。这里可以类比JAVA中的Object
package main
import "fmt"
func main() {
var a string
//pair<statictype:string , value: "abcd">
a="abcd"
//pair<type: value:>
var allType interface{}
//pair<concretetype:string , value: "abcd">
allType=a
//通过断言找到类型并打印对应的值
s,_ := allType.(string)
fmt.Println(s)
}
大家可以先理解一下
package main
import "fmt"
type Reader interface {
ReadBook()
}
type Writer interface {
WriterBook()
}
type Book2 struct {
}
func (this * Book2) ReadBook(){
fmt.Println("read book")
}
func (this * Book2) WriterBook(){
fmt.Println("writer book")
}
func main() {
//b: pair<type:Book value:book{}地址>
b:=&Book2{}
//r: pair<type: ,value: >
var r Reader
//r:pair<type:Book,value:book{}地址>
r=b
r.ReadBook()
var w Writer
//w: pair<type:Book,value:book{}地址>
//这里是断言,返回断言后的值---也可以看做是类型转换
//这里r和w具体的type是一致的
w=r.(Writer)
w.WriterBook()
}
例子1:
package main
import (
"fmt"
"reflect"
)
func reflectTest(arg interface{}){
fmt.Println("type: ",reflect.TypeOf(arg))
fmt.Println("value: ",reflect.ValueOf(arg))
}
func main() {
num:=1.23
reflectTest(num)
}
例子2:
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string
Age int
}
func (this User) Show(){
fmt.Println("name= ",this.Name," age= ",this.Age)
}
func reflectTest(arg interface{}){
typeOf := reflect.TypeOf(arg)
valueOf := reflect.ValueOf(arg)
fmt.Println("type: ",typeOf)
fmt.Println("value: ",valueOf)
//通过type,获取里面的字段
//1.获取interface的reflectType,通过Type得到NumField,进行遍历
//2.得到每个Field,数据类型
//3.通过filed有一个interface()方法得到对应的value
for i:=0; i<typeOf.NumField();i++ {
//输出字段类型相关的信息
fieldType:=typeOf.Field(i)
fmt.Println("当前field字段名: ",fieldType.Name," 字段所在包: ",fieldType.PkgPath,
" 字段类型: ",fieldType.Type," 字段索引: ",fieldType.Index,
"字段是否匿名: ",fieldType.Anonymous," 字段偏移量: ",fieldType.Offset,
" 字段的标签: ",fieldType.Tag)
//输出字段值相关的信息
//go语言里面struct里面变量如果大写则是public,如果是小写则是private的,private的时候通过反射不能获取其值
fieldVal:=valueOf.Field(i).Interface()
fmt.Println("当前字段的值为: ",fieldVal)
fmt.Println("-----------------------------------------------------------")
}
//通过type获取里面的方法,调用
method := typeOf.NumMethod()
fmt.Println("方法数量: ",method)
for j:=0;j<typeOf.NumMethod() ;j++ {
m:=typeOf.Method(j)
fmt.Println("方法名: ",m.Name," 方法类型: ",m.Type)
fmt.Println("-----------------------------------------------------------")
}
}
func main() {
user := User{Name: "大忽悠", Age: 18}
reflectTest(user)
}
package main
import (
"fmt"
"reflect"
)
type User struct {
Name string `info:"name"`
Age int `info:"age"`
}
func (this User) Show(){
fmt.Println("name= ",this.Name," age= ",this.Age)
}
func reflectTest(arg interface{}){
typeOf := reflect.TypeOf(arg)
for i:=0; i<typeOf.NumField();i++ {
//输出字段类型相关的信息
fieldType := typeOf.Field(i)
fmt.Println("当前field字段名: ", fieldType.Name, " 字段所在包: ", fieldType.PkgPath,
" 字段类型: ", fieldType.Type, " 字段索引: ", fieldType.Index,
"字段是否匿名: ", fieldType.Anonymous, " 字段偏移量: ", fieldType.Offset,
" 字段的标签: ", fieldType.Tag)
//获取标签里面某个属性的值
tag:= fieldType.Tag
info := tag.Get("info")
fmt.Println("标签中info对应的值为: ",info)
fmt.Println("---------------------------------------------------------")
}
}
func main() {
user := User{Name: "大忽悠", Age: 18}
reflectTest(user)
}
package main
import (
"encoding/json"
"fmt"
)
type Movie struct {
Title string `json:"title"`
Year int `json:"year"`
Price int `json:"rmb"`
Actors []string `json:"actors"`
}
func main() {
movie := Movie{Title: "大忽悠", Year: 2023, Price: 1000000, Actors: []string{"大忽悠", "小朋友"}}
//编码的过程: 将结构体转换为Json
jsonStr,err := json.Marshal(movie)
if err!=nil{
fmt.Println("json format error : ",err)
return
}
fmt.Printf("jsonStr = %s\n",jsonStr)
//解码的过程: jsonstr--->结构体
movie1 := Movie{}
err = json.Unmarshal(jsonStr, &movie1)
if err!=nil{
fmt.Println("json Unmarshal error : ",err)
return
}
fmt.Printf("movie1 %v\n",movie1)
}
OkHttp的作用 OkHttp is an HTTP client。 如果是HTTP的方式想得到数据,就需要我们在页面上输入网址,如果网址没有问题,就有可能返回对应的String字符串,如果这个地址
Record 一个重要的字符串算法,这是第三次复习。 通过总结我认为之所以某个算法总是忘记,是因为大脑始终没有认可这种算法的逻辑(也就是脑回路)。 本篇主要讲解从KMP的应用场景,
SQL 注入基础 【若本文有问题请指正】 有回显 回显正常 基本步骤 1. 判断注入类型 数字型 or 字符型 数字型【示例】:
标签: #Prompt #LLM 创建时间:2023-04-28 17:05:45 链接: 课程(含JupyterNotebook) , 中文版 讲师: An
Swift是供iOS和OS X应用编程的新编程语言,基于C和Objective-C,而却没有C的一些兼容约束。Swift采用了安全的编程模式和添加现代的功能来是的编程更加简单、灵活和有趣。界面则基于
红日靶机(一)笔记 概述 域渗透靶机,可以练习对域渗透的一些知识,主要还是要熟悉 powershell 语法,powershell 往往比 cmd 的命令行更加强大,而很多渗透开源的脚本都是 po
八大绩效域详细解析 18.1 干系人绩效域 跟干系人所有相关的活动. 一、预期目标 ①与干系人建立高效的工作关系 ②干系人认同项目目标 ③支持项目的干系人提高
18.3 开发方法和生命周期绩效域 跟开发方法,项目交付节奏和生命周期相关的活动和职能. 一、预期目标: ①开发方法与项目可交付物相符合; ②将项目交付与干系人价值紧密
18.7 度量绩效域 度量绩效域涉及评估项目绩效和采取应对措施相关的活动和职能度量是评估项目绩效,并采取适当的应对措施,以保持最佳项目绩效的过程。 一、 预期目标: ①对项目状况
pygraphviz 安装,windows系统: 正确的安装姿势: Prebuilt-Binaries/PyGraphviz at master · CristiFati/Prebuilt-Binar
今天给大家介绍IDEA开发工具如何配置devtools热加载工具。 1、devtools原理介绍 spring-boot-devtools是spring为开发者提供的热加载
一 什么是正则表达式 // 正则表达式(regular expression)是一个描述字符模式的对象; // JS定义RegExp类表示正则表达式; // String和RegExp都定义了使用
目前是2022-04-25 23:48:03,此篇博文分享到互联网上估计是1-2个月后的事了,此时的OpenCV3最新版是3.4.16 这里前提是gcc,g++,cmake都需要安装好。 没安装好的,
一、概述 1、Flink 是什么 Apache Flink is a framework and distributed processing engine for stateful comput
一、window 概述 Flink 通常处理流式、无限数据集的计算引擎,窗口是一种把无限流式数据集切割成有限的数据集进行计算。window窗口在Flink中极其重要。 二、window 类型 w
一、触发器(Trigger) 1.1、案例一 利用global window + trigger 计算单词出现三次统计一次(有点像CountWindow) 某台虚拟机或者mac 终端输入:nc -
一、时间语义 在Flink 中涉及到三个重要时间概念:EventTime、IngestionTime、ProcessingTime。 1.1、EventTime EventTime 表示日志事
一、概述 以wordcount为例,为什么每次输入数据,flink都能统计每个单词的总数呢?我们都没有显示保存每个单词的状态值,但是每来一条数据,都能计算单词的总数。事实上,flink在底层维护了每
一、概述 checkpoint机制是Flink可靠性的基石,可以保证Flink集群在某个算子因为某些原因(如 异常退出)出现故障时,能够将整个应用流图的状态恢复到故障之前的某一状态,保 证应用流图状
一、standalone 部署模式 1、下载安装包 下载安装包地址 有两种安装包类型: 第一种是带 Hadoop依赖的(整合YARN) 第二种是不带 Hadoop依赖的(Standalone模式)
我是一名优秀的程序员,十分优秀!