【Go基础】数据类型

news2024/9/25 17:10:47

文章目录

    • 1. 数据类型
      • 1.1 基本数据类型
      • 1.2 复合数据类型
      • 1.3 自定义数据类型
    • 2. 数组
    • 3. 切片
    • 4. 字符串
    • 5. 数据类型转换
    • 6. Map
    • 7. Channel

1. 数据类型

1.1 基本数据类型

类型长度(字节)默认值说明
bool1false
byte10uint8,取值范围[0,255]
rune40Unicode Code Point, int32
int, uint4或8032 或 64 位,取决于操作系统
int8, uint810-128 ~ 127, 0 ~ 255
int16, uint1620-32768 ~ 32767, 0 ~ 65535
int32, uint3240-21亿~ 21亿, 0 ~ 42亿,rune是int32 的别名
int64, uint6480
float3240.0
float6480.0
complex6480
complex128160
uintptr4或80以存储指针的 uint32 或 uint64 整数
fmt.Printf("os arch %s, int size %d\n", runtime.GOARCH, strconv.IntSize) // int是4字节还是8字节,取决于操作系统是32位还是64位
var a int = 5
var b int8 = 5
var c int16 = 5
var d int32 = 5
var e int64 = 5
var f uint = 5
var g uint8 = 5
var h uint16 = 5
var i uint32 = 5
var j uint64 = 5
fmt.Printf("a = %d, b = %d, c = %d, d = %d, e = %d, f = %d, g = %d, h = %d, i = %d, j=%d\n", a, b, c, d, e, f, g, h, i, j)
var k float32 = 5
var l float64 = 5
fmt.Printf("k = %f, l = %.2f\n", k, l) // %.2f保留2位小数
var m complex128 = complex(4, 7)
var n complex64 = complex(4, 7)
fmt.Printf("type of m is %T, type of n is %T\n", m, n) // %T输出变量类型
fmt.Printf("m=%v, n=%v\n", m, n) // 按值的本来值输出
fmt.Printf("m=%+v, n=%+v\n", m, n) // 在 %v 基础上,对结构体字段名和值进行展开
fmt.Printf("m=%#v, n=%#v\n", m, n) // 输出 Go 语言语法格式的值
fmt.Printf("m的实部%f, m的虚部%f\n", real(m), imag(m))
fmt.Printf("m的实部%e, m的虚部%g\n", real(m), imag(m)) // %e科学计数法,%g根据实际情况采用%e或%f格式(以获得更简洁、准确的输出)
o := true // 等价于var o bool = true
fmt.Printf("o=%t\n", o) // %t布尔变量
var pointer unsafe.Pointer = unsafe.Pointer(&a)
var p uintptr = uintptr(pointer)
var ptr *int = &a
fmt.Printf("p=%x pointer=%p ptr=%p\n", p, pointer, ptr) // %p输出地址,%x十六进制
var q byte = 100 // byte是uint,取值范围[0,255]
fmt.Printf("q=%d, binary of q is %b\n", q, q) // %b输出二进制
var r rune = '☻' // rune实际上是int32,即可以表示2147483647种字符,包括所有汉字和各种特殊符号
fmt.Printf("r=%d, r=%U\n", r, r) // %U Unicode 字符
var s string = "I'm Ricky"
fmt.Printf("s=%s\n", s)
var t error = errors.New("my error")
fmt.Printf("error is %v\n", t)
fmt.Printf("error is %+v\n", t) // 在 %v 基础上,对结构体字段名和值进行展开
fmt.Printf("error is %#v\n", t) // 输出 Go 语言语法格式的值

数值型变量的默认值是0,字符串的默认值是空字符串,布尔型变量的默认值是false,引用类型、函数、指针、接口的默认值是nil;数组的默认值取每个元素对应类型的默认值,结构体的默认值取每个成员变量对应类型的默认值

var a int
var b byte
var f float32
var t bool
var s string
var r rune
var arr [3]int
var slc []int

fmt.Printf("default value of int %d\n", a)
fmt.Printf("default value of byte %d\n", b)
fmt.Printf("default value of float %.2f\n", f)
fmt.Printf("default value of bool %t\n", t)
fmt.Printf("default value of string [%s]\n", s)
fmt.Printf("default value of rune %d, [%c]\n", r, r)
fmt.Printf("default int array is %v\n", arr) //取每个元素对应类型的默认值
fmt.Printf("default slice is nil %t\n", slc == nil)

输出:

default value of int 0
default value of byte 0
default value of float 0.00
default value of bool false
default value of string []
default value of rune 0, []
default int array is [0 0 0]
default slice is nil true

1.2 复合数据类型

类型默认值说明
array取每个元素对应类型的默认值值类型
struct取每个成员变量对应类型的默认值值类型
string“”UTF-8 字符串
slicenil引用类型
mapnil引用类型
channelnil引用类型
interfacenil接口
functionnil函数

1.3 自定义数据类型

类型别名

type byte = uint8
type rune = int32
type semaphore = uint8

自定义类型

type user struct {name string;age int}  // 用分号把多行代码隔开
type signal uint8
type ms map[string]string
type add func(a, b int) int

2. 数组

数组是块连续的内存空间,在声明的时候必须指定长度,且长度不能改变。所以数组在声明的时候就可以把内存空间分配好,并赋上默认值,即完成了初始化
在这里插入图片描述
一维数组初始化

var arr1 [5]int = [5]int{} // 数组必须指定长度和类型,且长度和类型指定后不可改变
var arr2 = [5]int{}
var arr3 = [5]int{3, 2} // 给前2个元素赋值
var arr4 = [5]int{2: 15, 4: 30} // 指定index赋值
var arr5 = [...]int{3, 2, 6, 5, 4}// 根据{}里元素的个数推断出数组的长度
var arr6 = [...]struct {
    name string
    age int
}{{"Tom", 18}, {"Jim", 20}} // 数组的元素类型由匿名结构体给定

二维数组初始化

// 5行3列,只给前2行赋值,且前2行的所有列还没有赋满
var arr1 = [5][3]int{{1}, {2, 3}}
// 第1维可以用...推测,第2维不能使用...
var arr2 = [...][3]int{{1}, {2, 3}}

访问数组里的元素

  • 通过index访问
    • 首元素 arr[0]
    • 末元素 arr[len(arr) - 1]
  • 访问二维数组里的元素
    • 位于第三行第四列的元素 arr[2][3]

遍历数组

// 遍历数组里的元素
for i, ele := range arr {
    fmt.Printf("index=%d, element=%d\n", i, ele)
}
// 也可以这样遍历数组
for i := 0; i < len(arr); i++ {
	// len(arr)获取数组的长度
    fmt.Printf("index=%d, element=%d\n", i, arr[i])
}
//遍历二维数组
for row, array := range arr {
	// 先取出某一行
    for col, ele := range array {
    	// 再遍历这一行
        fmt.Printf("arr[%d][%d]=%d\n", row, col, ele)
    }
}

通过for range遍历数组时取得的是数组里每一个元素的拷贝

arr := [...]int{1, 2, 3}
for i, ele := range arr {
	// ele是arr中元素的拷贝
    arr[i] += 8 // 修改arr里的元素,不影响ele
    fmt.Printf("%d %d %d\n", i, arr[i], ele)
    ele += 1 // 修改ele不影响arr
    fmt.Printf("%d %d %d\n", i, arr[i], ele)
}
for i := 0; i < len(arr); i++ {
    fmt.Printf("%d %d\n", i, arr[i])
}

在数组上调用cap()函数表示capacity容量,即给数组分配的内存空间可以容纳多少个元素;len()函数代表length长度,即目前数组里有几个元素;由于数组初始化之后长度不会改变,不需要给它预留内存空间,所以len(arr)==cap(arr);对于多维数组,其cap和len指第一维的长度

数组的长度和类型都是数组类型的一部分,函数传递数组类型时这两部分都必须吻合;go语言没有按引用传参,全都是按值传参,即传递数组实际上传的是数组的拷贝,当数组的长度很大时,仅传参开销都很大,如果想修改函数外部的数组,就把它的指针(数组在内存里的地址)传进来

// 参数必须是长度为5的int型数组(注意长度必须是5)
func update_array1(arr [5]int) {
	fmt.Printf("array in function, address is %p\n", &arr[0])
	arr[0] = 888
}

func update_array2(arr *[5]int) {
	fmt.Printf("array in function, address is %p\n", &((*arr)[0]))
	arr[0] = 888 // 因为传的是数组指针,所以直接在原来的内存空间上进行修改
}

3. 切片

切片是一个结构体,包含三个成员变量,array指向一块连续的内存空间,cap表示这块内存的大小,len表示目前该内存里存储了多少元素

type slice struct { 
    array unsafe.Pointer 
    len int 
    cap int 
}

切片的初始化

var s []int // 切片声明,len=cap=0
s = []int{} // 初始化,len=cap=0
s = make([]int, 3) // 初始化,len=cap=3
s = make([]int, 3, 5) // 初始化,len=3,cap=5
s = []int{1, 2, 3, 4, 5} // 初始化,len=cap=5
s2d := [][]int{
    {1},{2, 3}, // 二维数组各行的列数相等,但二维切片各行的len可以不等
}

切片相对于数组最大的特点就是可以追加元素,可以自动扩容。追加的元素放到预留的内存空间里,同时len加1,如果预留空间已用完,则会重新申请一块更大的内存空间,capacity大约变成之前的2倍(cap<1024)或1.25倍(cap>1024),把原内存空间的数据拷贝过来,在新内存空间上执行append操作

s := make([]int, 3, 5)
for i := 0; i < 3; i++ {
    s[i] = i + 1
}
fmt.Printf("s[0] address %p, s=%v\n", &s[0], s)
// capacity还够用,直接把追加的元素放到预留的内存空间上
s = append(s, 4, 5) // 可以一次append多个元素
fmt.Printf("s[0] address %p, s=%v\n", &s[0], s)
// capacity不够用了,得申请一片新的内存,把老数据先拷贝过来,在新内存上执行append操作
s = append(s, 6)
fmt.Printf("s[0] address %p, s=%v\n", &s[0], s)

通过指定起止下标,可以从大切片中截取一个子切片

s := make([]int, 3, 5) // len=3, cap=5
sub_slice = s[1:3] // len=2, cap=4

刚开始,子切片和母切片共享底层的内存空间,修改子切片会反映到母切片上,在子切片上执行append会把新元素放到母切片预留的内存空间上;当子切片不断执行append,耗完了母切片预留的内存空间,子切片跟母切片就会发生内存分离,此后两个切片没有任何关系
在这里插入图片描述

func sub_slice() {
	// 截取一部分,创造子切片,此时子切片与母切片(或母数组)共享底层内存空间,母切片的capacity子切片可能直接用
	s := make([]int, 3, 5)
	for i := 0; i < 3; i++ {
		s[i] = i + 1
	}
	fmt.Printf("s[1] address %p\n", &s[1])
	sub_slice := s[1:3] // 从切片创造子切片,len=cap=2
	fmt.Printf("len %d cap %d\n", len(sub_slice), cap(sub_slice))
	// 母切片的capacity还允许子切片执行append操作
	sub_slice = append(sub_slice, 6, 7) // 可以一次append多个元素
	sub_slice[0] = 8
	fmt.Printf("s=%v, sub_slice=%v, s[1] address %p, sub_slice[0] address %p\n", s, sub_slice, &s[1], &sub_slice[0])
	// 母切片的capacity用完了,子切片再执行append就得申请一片新的内存,把老数据先拷贝过来,在新内存上执行append操作,此时的append操作跟母切片没有任何关系
	sub_slice = append(sub_slice, 8)
	sub_slice[0] = 9
	fmt.Printf("s=%v, sub_slice=%v, s[1] address %p, sub_slice[0] address %p\n", s, sub_slice, &s[1], &sub_slice[0])

	arr := [5]int{1, 2, 3, 4, 5}
	fmt.Printf("arr[1] address %p\n", &arr[1])
	sub_slice = arr[1:3] // 从数组创造子切片,len=cap=2
	fmt.Printf("len %d cap %d\n", len(sub_slice), cap(sub_slice))
	// 母数组的capacity还允许子切片执行append操作
	sub_slice = append(sub_slice, 6, 7) // 可以一次append多个元素
	sub_slice[0] = 8
	fmt.Printf("arr=%v, sub_slice=%v, arr[1] address %p, sub_slice[0] address %p\n", arr, sub_slice, &arr[1], &sub_slice[0])
	// 母数组的capacity用完了,子切片再执行append就得申请一片新的内存,把老数据先拷贝过来,在新内存上执行append操作,此时的append操作跟母数组没有任何关系
	sub_slice = append(sub_slice, 8)
	sub_slice[0] = 9
	fmt.Printf("arr=%v, sub_slice=%v, arr[1] address %p, sub_slice[0] address %p\n", arr, sub_slice, &arr[1], &sub_slice[0])
}

Go语言函数传参,传的都是值,即传切片会把切片的{arrayPointer, len, cap}这3个字段拷贝一份传进来,由于传的是底层数组的指针,所以可以直接修改底层数组里的元素

func update_slice(s []int) {
	s[0] = 888
}
s := []int{1, 2, 3}
update_slice(s)
fmt.Printf("s=%v\n", s)

4. 字符串

字符串里面可以包含任意Unicode字符

s := " Ricky☻" 

字符串里也可以包含转义字符

s := "He say:\"I'm fine.\" \n\\Thank\tyou.\\" 

字符串也可以用反引号来定义,反引号里的转义字符无效,反引号里的内容原封不动地输出,包括空白符和换行符

s := `here is first line. 

  there is third line.
`

字符串常用操作

方法介绍
len(str)求长度
strings.Split分割
strings.Contains判断是否包含
strings.HasPrefix,strings.HasSuffix前缀/后缀判断
strings.Index(),strings.LastIndex()子串出现的位置
s := "born to win, born to die."
fmt.Printf("sentence length %d\n", len(s))
fmt.Printf("\"s\" length %d\n", len("s")) // 英文字母的长度为1
fmt.Printf("\"中\"  length %d\n", len("中")) // 一个汉字占3个长度
arr := strings.Split(s, " ")
fmt.Printf("arr[3]=%s\n", arr[3])
fmt.Printf("contain die %t\n", strings.Contains(s, "die"))          //包含子串
fmt.Printf("contain wine %t\n", strings.Contains(s, "wine"))        //包含子串
fmt.Printf("first index of born %d\n", strings.Index(s, "born"))    //寻找子串第一次出现的位置
fmt.Printf("last index of born %d\n", strings.LastIndex(s, "born")) //寻找子串最后一次出现的位置
fmt.Printf("begin with born %t\n", strings.HasPrefix(s, "born"))    //以xxx开头
fmt.Printf("end with die. %t\n", strings.HasSuffix(s, "die."))      //以xxx结尾

将多个字符串拼接成一个长字符串的几种方式

  • 使用加号连接
  • func fmt.Sprintf(format string, a ...interface{}) string
  • func strings.Join(elems []string, sep string) string
  • 当有大量的string需要拼接时,考虑使用strings.Builder,效率最高
s1 := "Hello"
s2 := "how"
s3 := "are"
s4 := "you"
merged := s1 + " " + s2 + " " + s3 + " " + s4
fmt.Println(merged)
merged = fmt.Sprintf("%s %s %s %s", s1, s2, s3, s4)
fmt.Println(merged)
merged = strings.Join([]string{s1, s2, s3, s4}, " ")
fmt.Println(merged)
sb := strings.Builder{}
sb.WriteString(s1)
sb.WriteString(" ")
sb.WriteString(s2)
sb.WriteString(" ")
sb.WriteString(s3)
sb.WriteString(" ")
sb.WriteString(s4)
sb.WriteString(" ")
merged = sb.String()
fmt.Println(merged)

string中每个元素叫“字符”,字符有两种

  • byte:1个字节,代表ASCII码的一个字符
  • rune:4个字节,代表一个UTF-8字符,一个汉字可用一个rune表示

注意事项

  • string是常量,不能修改其中的字符
  • string可以转换为[]byte或[]rune类型
  • string底层是byte数组,string的长度就是该byte数组的长度,UTF-8编码下一个汉字占3个byte,即一个汉字占3个长度
s1 := "today 晴天"
arr := []byte(s1)
brr := []rune(s1)
fmt.Printf("last byte %d\n", arr[len(arr)-1]) // string可以转换为[]byte或[]rune类型
fmt.Printf("last byte %c\n", arr[len(arr)-1]) // byte或rune可以转为string
fmt.Printf("last rune %d\n", brr[len(brr)-1])
fmt.Printf("last rune %c\n", brr[len(brr)-1])
L := len(s1)
fmt.Printf("string len %d byte array len %d rune array len %d\n", L, len(arr), len(brr))
for _, ele := range s1 {
    fmt.Printf("%c ", ele) // string中的每个元素是字符
}
fmt.Println()
for i := 0; i < L; i++ {
    fmt.Printf("%c ", s1[i]) // [i]前面应该出现数组或切片,这里自动把string转成了[]byte(而不是[]rune)
}

5. 数据类型转换

强制类型转换的基本方法就是把目标类型放在变量前面,把变量括起来

var i int = 9
var by byte = byte(i) // int转为byte
i = int(by) // byte转为int

注意事项

  • 低精度向高精度转换没问题,高精度向低精度转换会丢失位数
  • 无符号向有符号转换,最高位是符号位
  • byte和int可以相互转换
  • float和int可以相互转换,但是小数位会丢失
  • bool和int不能相互转换
  • 不同长度的int或float之间可以相互转换
// 高精度向低精度转换,数字很小时这种转换没问题
var ua uint64 = 1
i8 := int8(ua)
fmt.Printf("i8=%d\n", i8)

// 最高位的1变成了符号位
ua = uint64(math.MaxUint64)
i64 := int64(ua)
fmt.Printf("i64=%d\n", i64)

// 位数丢失
ui32 := uint32(ua)
fmt.Printf("ui32=%d\n", ui32)

// 单个字符可以转为int
var i int = int('a')
fmt.Printf("i=%d\n", i)

// byte和int可以互相转换
var by byte = byte(i)
i = int(by)
fmt.Printf("i=%d\n", i)

// float和int可以互相转换,小数位会丢失
var ft float32 = float32(i)
i = int(ft)
fmt.Printf("i=%d\n", i)

string和其他数据类型互转

var err error
var i int = 8
var i64 int64 = int64(i)
// int转string
var s string = strconv.Itoa(i) // Itoa内部实现是FormatInt
s = strconv.FormatInt(i64, 10)
// string转int
i, err = strconv.Atoi(s)
// string转int64
i64, err = strconv.ParseInt(s, 10, 64)

// float转string
var f float64 = 8.123456789
s = strconv.FormatFloat(f, 'f', 2, 64) // 转成float64并保留2位小数
fmt.Println(s)
// string转float
f, err = strconv.ParseFloat(s, 64)

// string<-->[]byte
var arr []byte = []byte(s)
s = string(arr)

// string<-->[]rune
var brr []rune = []rune(s)
s = string(brr)

fmt.Printf("err %v\n", err)

6. Map

Go中map的底层实现是hash table,根据key查找value的时间复杂度是O(1)
在这里插入图片描述
map的初始化

var m map[string]int // 声明map,指定key和value的数据类型
m = make(map[string]int) // 初始化,容量为0
m = make(map[string]int, 200) // 初始化,容量为5,建议初始化时给一个合适的容量,减少扩容的概率
m = map[string]int{"语文": 0, "数学": 39} // 初始化时直接赋值

添加和删除key

m["英语"] = 59 // 往map里添加key-value对
m ["英语"] = 70 // 更新
delete(m, "数学") // 从map里删除key-value对

len(m)获取map的长度,go不支持对map上执行cap函数
读取key对应的value时,如果key不存在,则返回value类型的默认值,所以建议先判断key是否存在

if value, exists := m["语文"]; exists {
    fmt.Println(value)
} else {
    fmt.Println("map里不存在[语文]这个key")
}

遍历map

// 遍历map
for key, value := range m {
    fmt.Printf("%s=%d\n", key, value)
}
fmt.Println("-----------")
// 多次遍历map返回的顺序是不一样的,但相对顺序是一样的,因为每次随机选择一个开始位置,然后顺序遍历
for key, value := range m {
    fmt.Printf("%s=%d\n", key, value)
}
fmt.Println("-----------")

// 一边遍历一边修改
for key, value := range m {
    m[key] = value + 1
}
for key, value := range m {
    fmt.Printf("%s=%d\n", key, value)
}
fmt.Println("-----------")

// for range取得的是值拷贝
for _, value := range m {
    value = value + 1
}
for key, value := range m {
    fmt.Printf("%s=%d\n", key, value)
}

map中的key可以是任意能够用==操作符比较的类型,不能是函数、map、切片,以及包含上述3中类型成员变量的的struct,value可以是任意类型。

type f func(int) bool
type m map[int]byte
type s []int

type i int

var m1 map[i]f
fmt.Println(m1)

// 函数、map、切片不能当key
// var m2 map[f]bool
// fmt.Println(m2)
// var m3 map[m]bool
// fmt.Println(m3)
// var m4 map[s]bool
// fmt.Println(m4)

type user struct {
	scores float32 // 如果scores是slice,则user不能作为map的key
}

u := user{}
m5 := make(map[user]interface{})
m5[u] = 5
fmt.Println(m5)

7. Channel

channel(管道)底层是一个环形队列(先进先出),send(插入)和recv(取走)从同一个位置沿同一个方向顺序执行,sendx表示最后一次插入元素的位置,recvx表示最后一次取走元素的位置
在这里插入图片描述

var ch chan int // 管道的声明
ch = make(chan int, 8) // 管道的初始化,环形队列里可容纳8个int
ch <- 1 // 往管道里写入(send)数据
ch <- 2
ch <- 3
ch <- 4
ch <- 5
v := <-ch //从管道里取走(recv)数据
fmt.Println(v)
v = <-ch
fmt.Println(v)
read_only := make (<-chan int) // 定义只读的channel
write_only := make (chan<- int) // 定义只写的channel

定义只读和只写的channel意义不大,一般用于在参数传递中

// 只能向channel里写数据 
func send(c chan<- int) { 
    c <- 1 
} 

// 只能取channel中的数据 
func recv(c <-chan int) {
	_ = <-c
}

// 返回一个只读channel
func (c *Context) Done() <-chan struct{} {
    return nil
}

可以通过for range的方式遍历管道,遍历前必须先关闭管道,禁止再写入元素

close(ch)
// 遍历管道里剩下的元素
for ele := range ch {
    fmt.Println(ele)
}

slice、map和channel是go语言里的3种引用类型,都可以通过make函数来进行初始化(申请内存分配),因为它们都包含一个指向底层数据结构的指针,所以称之为“引用”类型,引用类型未初始化时都是nil,可以对它们执行len()函数,返回0

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140290.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑解压文件丢失怎么找回来?四种恢复方法

您在使用电脑过程中&#xff0c;有没有解压过文件呢&#xff1f;如果有的话&#xff0c;是否出现过解压文件丢失的情况呢&#xff1f;解压文件通俗易懂地讲就是把压缩好了的文件解开。而有些小伙伴在解压文件以后发现丢失了&#xff0c;这些丢失的文件或许是您重要的img解压文件…

数学建模学习笔记-算法(求解整数规划-2.割平面算法)

基本思想 松弛问题无解&#xff0c;则整数规划无解 松弛问题的最优解是整数解&#xff0c;则他也是整数规划的最优解 如果松弛问题的解是非整数解&#xff0c;则对其增加割平面条件。 割平面条件&#xff1a;增加一个线性条件&#xff0c;通过不等式将可行区域割掉一部分&a…

如何使用ebpf统计某个端口的流量

前言 上篇文章我们已经初步使用kprobe来探测内核函数了, 这篇文章就在上篇文章的基础上做个修改, 通过kprobe探测内核函数tcp_sendmsg来统计tcp服务端的发送流量. 废话不多说, 直接上正文. 环境 tcp服务端运行在ubuntu22, 监听端口为6230, 其内核为5.19.0-26-generic, ebpf程序…

LSA、pLSA、LDA、NMF、BERTopic、Top2Vec进行主题建模

在自然语言处理(NLP)中,主题建模是一种技术,用于从文本数据中发现隐藏的语义主题(或主题)。这是一个无监督机器学习问题,即在没有标签或标签的情况下学习模式。主题建模的应用非常广泛,可用于搜索引擎、情感分析、新闻聚类和摘要生成等许多任务。 在这里将探讨主题建模…

一屏统管 智慧交管Web3D可视化大屏云控系统

交通是城市发展的基础&#xff0c;体现着社会文明程度&#xff0c;彰显着城市治理水平。今天给大家分享一个基于 数维图 的 Sovit3D编辑器 构建轻量化 3D 可视化场景的案例——智慧交管三维可视化系统。多维度呈现城市交通情况&#xff0c;赋能“安全管控、缓堵保畅、出行服务”…

硬件系统工程师宝典(2)-----硬件电路的概要设计启动

今天我们继续来读这本书&#xff0c;硬件系统工程师宝典。作者提到&#xff0c;产品需求分析之后就进入概要设计阶段。在这个阶段&#xff0c;ID&#xff08;Industrial Design&#xff09;工业设计及结构工程师、软件系统开发工程师和硬件系统开发工程师等开始分头工作。 工业…

头条百科词条怎么编辑?送你一份超详细指南

头条百科其实就是之前的互动百科&#xff0c;后面被今日头条收购之后&#xff0c;改为头条百科&#xff0c;也叫快懂百科。 百度百科在百度上的权重很高&#xff0c;而头条百科在今日头条和抖音上的权重很高。 现在我们遇到什么问题或是不知道什么人物、品牌的时候&#xff0…

xxljob 的 阻塞处理策略的逻辑是什么(小白)

目录 1 需求2 单机串行3 丢弃后续调整4 覆盖之前的调整1 需求 每一个任务都有一个阻塞处理策略,我们在创建任务的时候可以自己设置,那么不同的设置,后端的逻辑是什么呢》 xxljob 调度中心项目 调度我们自己的项目,到了我们项目里面,最先到的文件是 就在首次到的这个文件的…

Springboot-数据库操作(Mybatis)-初级入门

一、Mybatis-plus介绍 官方文档&#xff1a;简介 | MyBatis-Plus (baomidou.com) 他只增强了单表查询&#xff0c;没增强多表查询等复杂的查询。 二、配置 引入依赖 <!-- MyBatisPlus依赖--><dependency><groupId>com.baomidou</groupId><a…

UBUNTU 22.04 使用 SUNSHINE 和 MOONLIGHT 进行串流

参考 【ubuntu22.04】sunshine安装使用总结&#xff0c;远程游戏。_哔哩哔哩_bilibili sunshine/README.md at master loki-47-6F-64/sunshine GitHub GitHub - LizardByte/Sunshine: Sunshine is a Gamestream host for Moonlight. Installation - Sunshine documentati…

基于Java+SpringBoot+vue实现图书借阅和销售商城一体化系统

基于JavaSpringBootvue实现图书借阅和销售商城一体化系统 &#x1f680; 博主介绍&#xff1a;5年java开发经验&#xff0c;专注Java开发、定制、远程、文档编写指导等,csdn特邀作者、专注于Java技术领域 &#x1f345; 作者主页 超级帅帅吴 &#x1f345; 欢迎点赞 &#x1f…

2023年江苏专转本志愿填报辅导(22上岸南工程学长辅导手册)

文章目录公告链接一、23年专转本与22年的变化二、专转本志愿填报2.1、填报流程2.2、志愿填报院校顺序选择参考三、专转本考试分值及时间节点四、专转本录取投档原则及办法&#xff08;平行、征求平行志愿、服从志愿、降分录取&#xff09;五、考前冲刺辅导不同大类填报计算机大…

面试官问我TCP三次握手和四次挥手,我真的是

候选者&#xff1a;面试官你好&#xff0c;请问面试可以开始了吗 面试官&#xff1a;嗯&#xff0c;开始吧 面试官&#xff1a;今天来聊聊TCP吧&#xff0c;TCP的各个状态还有印象吗&#xff1f; 候选者&#xff1a;还有些许印象的&#xff0c;要不我就来简单说下TCP的三次握…

【Kotlin】函数 ⑤ ( 匿名函数变量类型推断 | 匿名函数参数类型自动推断 | 匿名函数又称为 Lambda 表达式 )

文章目录一、匿名函数变量类型推断二、匿名函数参数类型自动推断三、Lambda 表达式一、匿名函数变量类型推断 定义变量 时 , 如果将变量值 直接赋值给该变量 , 那么就可以 不用显示声明该变量的类型 ; 下面的代码中 , 定义 name 变量 , 为其 赋值 “Tom” 字符串 String 类型变…

2023年山东食品安全管理员模拟试题及答案

百分百题库提供食品安全管理员考试试题、食品安全管理员考试预测题、食品安全管理员考试真题、食品安全管理员证考试题库等&#xff0c;提供在线做题刷题&#xff0c;在线模拟考试&#xff0c;助你考试轻松过关。 一、单选题 1.餐饮具消毒的目的是: A.去除表面的污垢 B.杀灭…

【个人博客】Hexo个人博客搭建与配置详细教程 + Fluid主题 + Gitee发布

文章目录一、环境准备1.1 安装 NodeJs1.2 安装 Git1.3 安装 Hexo二、Gitee仓库搭建2.1 Gitee账号注册2.2 仓库搭建三、Hexo博客搭建3.1 基础环境搭建3.2 启动 Hexo3.3 更换 Fluid 主题四、自定义配置4.1 全局设置4.1.1 页面顶部大图4.1.2 博客标题4.1.3 导航菜单4.1.4 懒加载4.…

路由器连接实验

使用静态路由实现全网连通 R1 [r1]interface GigabitEthernet 0/0/0 [r1-GigabitEthernet0/0/0]ip address 12.1.1.1 24 [r1]interface GigabitEthernet 0/0/1 [r1-GigabitEthernet0/0/1]ip ad [r1-GigabitEthernet0/0/1]ip address 14.1.1.1 24 [r1]interface LoopBack 0 [r1…

搞懂MyBatis?这篇文章就够了~

哈喽呀~你好呀~欢迎呀~一起来看看这篇宝藏文章吧~ 目录 1.什么是MyBatis 2.配置MyBatis开发环境 3.使用MyBatis框架去操作数据库 3.1 实现MyBatis查询功能. 3.1.1 创建一个接口(该接口一定要加上Mapper注解): 3.1.2 创建上面接口对应的 xml 文件 (此文件会实现接口中的…

易基因|METTL3 通过调节m6A 修饰抑制口腔鳞状细胞癌安罗替尼敏感性| 肿瘤研究

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。2022年9月27日&#xff0c;中山大学附属第一医院口腔颌面外科王安训和何倩婷课题组在《Cancer Cell International》杂志发表了《METTL3 suppresses anlotinib sensitivity by regulating …

Tomcat弱口令+后端getshell漏洞

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是Tomcat弱口令后端getshell漏洞。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁…