go语言试用标准c 库,Go语言开发(十三)、Go语言常用标准库三

2023-10-27

Go语言开发(十三)、Go语言常用标准库三

一、sync

1、sync简介

sync提供基本的同步原语,如sync.Mutex,sync.RWMutex,sync.Once,sync.Cond,sync.Waitgroup,除了Once和WaitGroup类型外,大多数类型都供低级库使用。Go语言中,不要通过共享内存通信,而要通过通信共享内存,通过Channel和沟通可以更好地完成更高级别的同步。

type Locker interface {

Lock()

Unlock()

}

Locker提供了锁的两个操作方法,Lock、Unlock。

2、sync.Mutex

sync.Mutex是互斥锁,是Locker的一种实现。

一个互斥锁只能同时被一个goroutine锁定,其它goroutine将阻塞直到互斥锁被解锁(重新争抢对互斥锁的锁定)。

sync.Mutex使用注意:

(1)在首次使用后不要复制互斥锁。

(2)对一个未锁定的互斥锁解锁将会产生运行时错误。

使用示例:

package main

import (

"fmt"

"sync"

"time"

)

var locker sync.Mutex

func mutexDemo() {

var value int = 0

for i := 0; i < 100; i++ {

go func(i int) {

locker.Lock()

defer locker.Unlock()

fmt.Printf("Goroutine %d : value: %d\n", i, value)

value++

}(i)

}

}

func main() {

mutexDemo()

time.Sleep(time.Second)

}

3、sync.Pool

sync.Pool 临时对象池用于存储临时对象,将使用完毕的对象存入对象池中,在需要的时候取出来重复使用,目的是为了避免重复创建相同的对象造成GC负担过重。如果对象不再被其它变量引用,存放的临时对象可能会被GC回收掉。

type Pool struct {

// 创建临时对象的函数

New func() interface{}

}

// 向临时对象池中存入对象

func (p *Pool) Put(x interface{})

// 从临时对象池中取出对象

func (p *Pool) Get() interface{}

从sync.Pool中取出对象时,如果Pool中没有对象,将返回nil,但如果给 Pool.New字段指定一个函数,Pool将使用指定函数创建一个新对象返回。

sync.Pool可以安全的在多个goroutine中并行使用,但并不适用于所有空闲对象,应该用来管理并发的例程共享的临时对象,而不应该管理短寿命对象中的临时对象。

sync.Pool使用示例如下:

package main

import (

"bytes"

"io"

"os"

"sync"

"time"

)

var bufPool = sync.Pool{

New: func() interface{} {

return new(bytes.Buffer)

},

}

func Log(w io.Writer, key, val string) {

// 获取临时对象,没有则自动创建

b := bufPool.Get().(*bytes.Buffer)

b.Reset()

b.WriteString(time.Now().Format(time.RFC3339))

b.WriteByte(' ')

b.WriteString(key)

b.WriteByte('=')

b.WriteString(val)

w.Write(b.Bytes())

// 将临时对象放回到Pool中

bufPool.Put(b)

}

func main() {

Log(os.Stdout, "key", "value")

}

// output:

// 2018-12-31T15:57:27+08:00 key=value

4、sync.Once

sync.Once可以使得函数多次调用只执行一次。

type Once struct {

m Mutex

done uint32

}

func (o *Once) Do(f func())

用done来记录执行次数,用互斥锁m来保证仅被执行一次。只有一个Do方法,调用执行。

利用sync.Once实现单例模式代码如下:

package Singleton

import (

"sync"

)

type Singleton map[string]string

var (

instance Singleton

once sync.Once

)

func New() Singleton{

once.Do(func() {

instance = make(Singleton)

})

return instance

}

使用示例如下:

package main

import (

"fmt"

"DesignPattern/Singleton"

)

func main() {

instance1 := Singleton.New()

instance1["name"] = "Jack Bauer"

instance2 := Singleton.New()

fmt.Println("My name is", instance2["name"])

}

// output:

// My name is Jack Bauer

5、sync.RWMutex

sync.RWMutex是针对读写操作的互斥锁,读写锁与互斥锁最大的不同就是可以分别对读、写进行锁定。一般用在大量读操作、少量写操作的情况。sync.RWMutex提供四种操作方法:

func (rw *RWMutex) Lock()

func (rw *RWMutex) Unlock()

func (rw *RWMutex) RLock()

func (rw *RWMutex) RUnlock()

RLock对读操作进行锁定,RUnlock对读锁定进行解锁,Lock对写操作进行锁定,Unlock对写锁定进行解锁。

sync.RWMutex锁定规则如下:

(1)同时只能有一个goroutine能够获得写锁定。

(2)同时可以有任意多个gorouinte获得读锁定。

(3)同时只能存在写锁定或读锁定(读和写互斥)。

(4)当有一个goroutine获得写锁定,其它无论是读锁定还是写锁定都将阻塞直到写解锁;当有一个goroutine获得读锁定,其它读锁定任然可以继续;当有一个或任意多个读锁定,写锁定将等待所有读锁定解锁后才能够进行写锁定。

sync.RWMutex读写锁使用注意:

(1)在首次使用之后,不要复制读写锁。

(2)不要混用锁定和解锁,如:Lock和RUnlock、RLock和Unlock。对未读锁定的读写锁进行读解锁或对未写锁定的读写锁进行写解锁将会引起运行时错误。

使用示例代码:

package main

import (

"fmt"

"sync"

"time"

)

var rw sync.RWMutex

func RWMutexDemo() {

var value int = 0

for i := 0; i < 10; i++ {

go func(i int) {

rw.Lock()

defer rw.Unlock()

fmt.Printf("Goroutine %d : Write value: %d\n", i, value)

value++

}(i)

go func(i int) {

rw.RLock()

defer rw.RUnlock()

fmt.Printf("Goroutine %d : Read value: %d\n", i, value)

}(i)

}

}

func main() {

RWMutexDemo()

time.Sleep(time.Minute)

}

6、sync.WaitGroup

sync.WaitGroup用于等待一组goroutine结束。

sync.WaitGroup操作方法如下:

func (wg *WaitGroup) Add(delta int)

func (wg *WaitGroup) Done()

func (wg *WaitGroup) Wait()

Add用来添加goroutine的个数。Done执行一次数量减1。Wait用来等待结束。

sync.WaitGroup使用示例如下:

package main

import (

"fmt"

"sync"

)

var wg sync.WaitGroup

func WaitGroupDemo() {

var value int = 0

for i := 0; i < 10; i++ {

wg.Add(1)

go func(i int) {

defer wg.Done()

fmt.Printf("Goroutine %d : Write value: %d\n", i, value)

value++

}(i)

wg.Add(1)

go func(i int) {

defer wg.Done()

fmt.Printf("Goroutine %d : Read value: %d\n", i, value)

}(i)

}

}

func main() {

WaitGroupDemo()

wg.Wait()

}

7、sync.Cond

sync.Cond实现一个条件等待变量,即等待或宣布事件发生的goroutine的会合点。

func NewCond(l Locker) *Cond

func (c *Cond) Broadcast()

func (c *Cond) Signal()

func (c *Cond) Wait()

NewCond用于根据Locker创建一个条件等待变量,Wait用于让一个goroutine等待通知,Signal用于单次发送通知让等待的goroutine继续,Broadcast用于广播通知让所有等待的goroutine继续。

sync.Cond条件等待变量实现生产者-消费者模式示例如下:

package main

import (

"fmt"

"math/rand"

"sync"

"time"

)

var locker = new(sync.Mutex)

var cond = sync.NewCond(locker)

var capacity = 10

var consumerNum = 5

var producerNum = 2

func Produce(out chan

for i := 0; i < producerNum; i++ {

go func(nu int) {

for {

cond.L.Lock()

for len(out) == capacity {

fmt.Println("Capacity Full, stop Produce")

cond.Wait()

}

num := rand.Intn(100)

out

fmt.Printf("Producer %d produce: num %d\n", nu, num)

cond.L.Unlock()

cond.Signal()

time.Sleep(time.Microsecond * 500)

}

}(i)

}

}

func Consume(in

for i := 0; i < consumerNum; i++ {

go func(nu int) {

for {

cond.L.Lock()

for len(in) == 0 {

fmt.Println("Capacity Empty, stop Consume")

cond.Wait()

}

num :=

fmt.Printf("Consumer %d: consume num %d\n", nu, num)

cond.L.Unlock()

time.Sleep(time.Second)

cond.Signal()

}

}(i)

}

}

func main() {

rand.Seed(time.Now().UnixNano())

quit := make(chan bool)

ProductPool := make(chan int, capacity)

Produce(ProductPool)

Consume(ProductPool)

}

二、reflect

1、reflect简介

在计算机科学领域,反射是指能够自描述和自控制的应用。反射通过采用某种机制来实现对自己行为的描述(self-representation)和监测(examination),并能根据自身行为的状态和结果,调整或修改应用所描述行为的状态和相关的语义。

每种语言的反射模型都不同,并且某些语言不支持反射。Golang语言通过reflect包实现反射机制,在运行时动态的调用对象的方法和属性。

Go语言中的变量包括(type, value)两部分,type包括static type和concrete type。static typ是编码时的类型(如int、string),concrete type是runtime的类型。

类型断言能否成功,取决于变量的concrete type,而不是static type。因此,一个reader变量如果其concrete type实现了write方法,也可以被类型断言为writer。

Golang指定类型变量的类型是静态类型,在创建变量时类型就已经确定,因此,反射主要与Golang的interface类型相关(type是concrete type)。

在Golang的实现中,每个interface变量都有一个(value, type)对用于记录变量的实际值和类型。value是变量的实际值,type是变量的实际类型。interface类型的变量包含2个指针,一个指针指向值的类型(concrete type),另一个指针指向实际的值(value)。

2、reflect接口

func TypeOf(i interface{}) Type

TypeOf用来动态获取输入参数接口中的值的类型,如果接口为空则返回nil。

func ValueOf(i interface{}) Value

ValueOf用来获取输入参数接口中的数据的值,如果接口为空则返回0。

reflect.ValueOf(interface)得到一个relfect.Value变量,可以通过relfect.Value本身的Interface()方法获得接口变量的真实内容,然后可以通过类型判断进行转换,转换为原有真实类型。真实类型可能是已知原有类型,也可能是未知原有类型。

对于已知原有类型:

package main

import (

"fmt"

"reflect"

)

func main() {

var num float64 = 3.14

value := reflect.ValueOf(num)

pointer := reflect.ValueOf(&num)

fmt.Println("value: ", value.Interface().(float64))

fmt.Println("value: ", pointer.Interface().(*float64))

fmt.Println("type: ", reflect.TypeOf(num))

}

// output:

// value: 3.14

// value: 0xc42001e0e8

// type: float64

对于未知原有类型,需要进行遍历探测其Filed:

package main

import (

"fmt"

"reflect"

)

type Student struct {

Name string

ID int

Age int

}

func (student Student) Print() {

fmt.Printf("%s's ID is %d, %d years.", student.Name, student.ID, student.Age)

}

func handleFieldAndMethod(input interface{}) {

inputType := reflect.TypeOf(input)

fmt.Println("type: ", inputType.Name())

inputValue := reflect.ValueOf(input)

fmt.Println("value: ", inputValue)

// 获取方法字段

// 1. 先获取interface的reflect.Type,然后通过NumField进行遍历

// 2. 再通过reflect.Type的Field获取其Field

// 3. 最后通过Field的Interface()得到对应的value

for i := 0; i < inputType.NumField(); i++ {

field := inputType.Field(i)

value := inputValue.Field(i).Interface()

fmt.Printf("%s %v %v\n", field.Name, field.Type, value)

}

// 获取方法

// 1. 先获取interface的reflect.Type,然后通过.NumMethod进行遍历

for i := 0; i < inputType.NumMethod(); i++ {

m := inputType.Method(i)

fmt.Printf("%s: %v\n", m.Name, m.Type)

}

}

func main() {

bauer := Student{"Bauer", 1, 130}

handleFieldAndMethod(bauer)

}

// output:

// type: Student

// value: {Bauer 1 130}

// Name string Bauer

// ID int 1

// Age int 130

// Print: func(main.Student)

func (v Value) MethodByName(name string) Value

MethodByName返回一个函数值对应的reflect.Value方法的名字。

func (v Value) Call(in []Value) []Value

Call方法将最终调用真实的方法,参数必须一致。

package main

import (

"fmt"

"reflect"

)

type Student struct {

Name string

ID int

Age int

}

func (student Student) Print() {

fmt.Printf("%s's ID is %d, %d years.", student.Name, student.ID, student.Age)

}

func CallMethod() {

student := Student{"Bauer", 1, 20}

value := reflect.ValueOf(student)

methodValue := value.MethodByName("Print")

// 对于无参函数

args := make([]reflect.Value, 0)

methodValue.Call(args)

}

func main() {

CallMethod()

}

// output:

// Print: func(main.Student)

三、runtime

1、runtime简介

Go语言编译器产生本地可执行代码,可执行代码仍旧运行在Go的 runtime中,runtime负责管理包括内存分配、垃圾回收、栈处理、goroutine、channel、切片(slice)、map 和反射(reflection)等。

runtime与C标准库的作用一样都是为了语言的跨平台性,runtime可以运行在Windows和Unix平台,可以运行在Intel或ARM处理器上。Go程序都附带runtime,runtime负责与底层操作系统交互。

2、runtime常用方法

runtime.Gosched()

让当前goroutine让出 cpu 以让其它goroutine运行,不会挂起当前线程,因此当前线程未来会继续执行。

func NumCPU() int

获取当前系统的逻辑CPU 核数量

runtime.GOMAXPROCS(i int)

设置最大的可同时使用的 CPU

通过runtime.GOMAXPROCS函数,应用程序何以在运行期间设置运行时系统中得逻辑处理器P最大数量。应在应用程序最早的调用。并且最好的设置P最大值的方法是在运行Go程序之前设置好操作程序的环境变量GOMAXPROCS,而不是在程序中调用runtime.GOMAXPROCS函数。

无论传递给函数的整数值是什么值,运行时系统的P最大值总会在1~256之间。

runtime.Goexit()

退出当前 goroutine(但defer语句会照常执行)

runtime.Goexit函数被调用后,会立即使调用他的Groution的运行被终止,但其他Goroutine并不会受到影响。runtime.Goexit函数在终止调用它的Goroutine的运行之前会先执行该Groution中还没有执行的defer语句。

runtime.NumGoroutine()

获取正在执行和排队的任务总数

runtime.NumGoroutine函数在被调用后,会返回系统中的处于特定状态的Goroutine的数量。这里的特指是指Grunnable\Gruning\Gsyscall\Gwaition。处于这些状态的Groutine即被看做是活跃的或者说正在被调度。

注意:垃圾回收所在Groutine的状态也处于这个范围内的话,也会被纳入该计数器。

runtime.GOOS

获取目标操作系统

func GOROOT() string

获取当前GOROOT

3、cgo

CGO是实现Go与C互操作的方式,包括Go调C和C调Go两个过程。Go调用C需要在程序中引入的一个伪包,import “C”即为在Go中使用的伪包。C伪包会在编译前被CGO工具捕捉到,并做一些代码的改写和桩文件的生成,不会被Go编译器见到。

Go语言中调用C程序的方法如下:

//自定义函数调用

package main

/*

#include

#include

void output(char *str) {

printf("%s\n", str);

}

*/

import "C"

import "unsafe"

func main() {

str := C.CString("hello cgo")

C.output(str)

C.free(unsafe.Pointer(str))

}

4、调度器

每一个Go程序都附带一个runtime,runtime负责与底层操作系统交互,也都会有scheduler对goruntines进行调度。

四、plugin

1、plugin简介

Golang是静态编译型语言,在编译时就将所有引用的包全部加载打包到最终的可执行程序中,因此不能在运行时动态加载其它共享库。Go 1.8开始,Go语言Linux和MacOS版本通过plugin包提供插件化加载共享库机制,能够在运行时动态加载外部功能。

2、plugin常用方法

type Plugin struct {

pluginpath string

err string // set if plugin failed to load

loaded chan struct{} // closed when loaded

syms map[string]interface{}

}

func Open(path string) (*Plugin, error)

func (p *Plugin) Lookup(symName string) (Symbol, error)

type Symbol interface{}

Open: 根据参数path提供的插件路径加载插件,并返回插件结构的指针*Plugin。

Lookup: *Plugin的惟一方法,通过名称symName在插件中寻找对应的变量或方法,以Symbol的形式返回。从插件中找到的任何元素都是以Symbol形式(即interface{})返回,需要通过断言的形式对结果进行判断和转换,得到需要的类型。

3、插件编译方法

Go语言编译器使用-buildmode=plugin标记编译生成一个插件(共享对象库文件)。Go包中导出的函数和变量被公开为ELF符号,可以使用plugin包在运行时查找并绑定ELF符号。

go build -buildmode=plugin -o xxxplugin.so xxxplugin.go

如果要想更好的控制插件版本,实现热更新插件,可以采用自动注册插件方式。当新版本插件加载后,自动注册插件版本号,插件平台里优先使用新版本插件的方法。

4、插件使用示例

插件编写HelloPlugin.go:

package main

import (

"fmt"

)

func init() {

fmt.Println("Hello")

}

func Hello() {

fmt.Println("world")

}

插件编译:

go build -buildmode=plugin -o HelloPlugin.so HelloPlugin.go

插件调用main.go:

package main

import (

"fmt"

"plugin"

)

func main() {

open, err := plugin.Open("./HelloPlugin.so")

if err != nil {

fmt.Println(err.Error())

}

symbol, err := open.Lookup("Hello")

if err != nil {

fmt.Println(err)

}

symbol.(func())()

}

编译运行:

go run main.go

5、插件化编程

插件管理器实现:

package PluginManager

import "fmt"

// 插件容器

var Plugins map[string]Plugin

func init() {

Plugins = make(map[string]Plugin)

}

type Plugin interface {

Start()

}

// 启动这个容器中所有的插件

func Start() {

for name, plugin := range Plugins {

go plugin.Start()

fmt.Printf("%s Plugin Start.\n", name)

}

}

// 插件做完之后必须得插入到容器中

func Register(name string, plugin Plugin) {

Plugins[name] = plugin

}

插件实现:

package HelloPlugin

import (

"GoExample/Plugin/PluginManager"

"fmt"

)

type HelloPlugin struct {

}

// 导入包时注册插件

func init() {

plugin := HelloPlugin{}

PluginManager.Register("HelloPlugin", plugin)

}

func (this HelloPlugin) Start() {

fmt.Println("This is HelloPlugin.")

}

插件使用:

package main

import "GoExample/Plugin/PluginManager"

import _ "GoExample/Plugin/HelloPlugin"

func main() {

PluginManager.Start()

}

// output:

// HelloPlugin Plugin Start.

五、signal

1、signal简介

os/signal包可以实现对信号的处理,Notify方法用来监听收到的信号,Stop方法用来取消监听。

func Notify(c chan < - os.Signal, sig ...os.Signal)

Notify函数会将进程收到的系统Signal转发给channel c,转发哪些信号由可变参数决定,SIGKILL和SIGSTOP不能被拦截和处理。

参数c表示接收信号的channel,后续参数表示设置要监听的信号,如果不设置表示监听所有的信号。

func Stop(c chan < - os.Signal)

Stop方法取消监听通道上的所有信号。

2、signal示例

package main

import (

"fmt"

"os"

"os/signal"

"syscall"

)

func main() {

signalChannel := make(chan os.Signal, 1)

done := make(chan bool, 1)

// 监听SIGINT、SIGTERM

signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM)

go func(ch chan os.Signal) {

// 接收信号

channel :=

fmt.Printf("Received a signal: %s\n", channel)

done

}(signalChannel)

// signal.Stop(signalChannel)

for {

fmt.Println("Waiting signal.")

fmt.Println("Exiting.")

}

}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

go语言试用标准c 库,Go语言开发(十三)、Go语言常用标准库三 的相关文章

  • Web安全常见漏洞原理、危害及其修复建议

    web安全常见漏洞原理 危害及其修复建议 一 SQL注入漏洞 原理 危害 修复建议 二 XSS漏洞 原理 危害 修复建议 三 CSRF漏洞 原理 危害 修复建议 四 SSRF漏洞 原理 危害 预防建议 五 文件上传漏洞 原理 危害 修复建议
  • 弗洛伊德算法(floyd)

    算法背景 图中的A B C D E F G 代表7个村庄 边上的权值带表两村庄之间的距离 现在要从某一个村庄 例如G村庄 往另外几个村庄送邮件 问任意一村庄到其他各村庄的最短距离分别是多少 思路 该问题实际是求从任一顶点到其余顶点的最短距离
  • 揭秘京东城市时空数据引擎—JUST如何助力交通流量预测

    2014年跨年夜上海外滩人流隐患事件 使得公共安全问题受到了全体社会的广泛关注 解决这一问题的很重要一项工作就是 如何实时监控和快速预测城市中每个地方的人流量 当某个地方的人流量超过给定的值或者有超过给定值的趋势时 相关部门能及时地采取相关
  • Python学习笔记(六):数据可视化

    1 使用matplotlib绘制图形 1 1 绘制折线图 import matplotlib pyplot as plt b 1 2 3 4 5 6 7 a 1 4 9 16 25 36 49 plt plot b a linewidth
  • js在控制台输出菱形

    js在控制台输出菱形 以一个上半部分10行 下半部分9行的为例 var str 在控制台输出要采用字符串拼接 所以先定义一个空字符串 for var row 1 row lt 10 row 外层循环控制行数 先输出上半部分的10行 for
  • HTTPOXY -- CGI 环境变量劫持漏洞分析

    0x00 前言 昨晚 一个名为 HTTPOXY 的漏洞在安全圈内广泛传播 云盾攻防对抗团队第一时间对此漏洞进行了深入分析 发现其本质是一个 CGI 环境变量劫持漏洞 对 CGI 的环境变量 HTTP PROXY 变量进行劫持 如果 CGI
  • Python作业

    提示 文章写完后 目录可以自动生成 如何生成可参考右边的帮助文档 文章目录 python安装步骤 打开官网 https www python org downloads windows 下载中心 测试安装是否成功 windows gt 运行
  • BurpSuite学习:在火狐浏览器使用foxyproxy添加代理127.0.0.1后无法正常上网

    个人认为 因为127 0 0 1就是本机上的本地服务器 它应该不具备服务器的功能 所以浏览器向本地服务器发送请求也不会转发到外网 更不会得到回应 打开burpsuite 它会承担服务器的作用转发请求 这时候浏览器会显示应该是请求被拦截之类的
  • 基于zinx的go tcp通信案例

    基于zinx的go tcp通信示例 一 zinx简介 https gitee com Aceld zinx Zinx是一个基于Golang的轻量级tcp服务框架 根据官方的定位 zinx是在游戏领域或者其他长链接的领域的轻量级企业框架 其使
  • Android RecyclerView对应的适配器中方法的执行顺序和具体作用详解

    前些天发现了一个蛮有意思的人工智能学习网站 8个字形容一下 通俗易懂 风趣幽默 感觉非常有意思 忍不住分享一下给大家 点击跳转到教程 1 代码的执行顺序为 首次进入会先调用getItemCount 返回条目的个数 之后会分别调用 getIt
  • 十大经典排序算法(动态演示+代码)-桶排序

    桶排序 桶排序 Bucket sort 或所谓的箱排序 是一个排序算法 工作的原理是将数组分到有限数量的桶里 每个桶再个别排序 有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排序 最后依次把各个桶中的记录列出来记得到有序序列 桶排
  • Qt中解除按键在聚焦时键盘空格键可以控制

    Qt中解除按键在聚焦时键盘空格键可以控制 只允许鼠标左键可以点击按键 首先需要知道原因 为什么键盘上的空格键也可以点击按键 根据Qt官网说明 A push button emits the signal clicked when it is
  • vue 前端导出excel xlsx插件 修改表格行高列宽度

    cnpm install xlsx save import XLSX from xlsx 列表页引入 表格导出 handleExport if this tableData total 0 this message error 暂无数据 t
  • SpringBoot 对接微信公众号模板消息通知

    效果图见测试结果 有问题评论 模板消息 开通模板消息功能 登录微信公众平台开通模板消息功能 未开通时 添加模板消息 审核通过后 登录微信公众平台 点击 广告与服务 gt 模板消息 公众号如果未设置服务类目 则需要先设置服务类目 然后在模板库
  • html通过id设置css样式,使用ID值如何应用CSS样式?

    假设你一个ID为 mytext 的HTML段落标记 如下面的代码片段所示 This is HTML interview questions 你可以使用有着 id 名称的 选择器创建一个样式 并应用CSS值到段落标记 为了应用样式到 myte
  • [spring] 注解@Autowired是如何实现的

    Table of Contents 前言 Autowired注解用法 Autowired注解的作用到底是什么 Autowired注解是如何实现的 例子注解 Override 自己实现一个注解 Autowired注解实现逻辑分析 问题 注解的
  • LaTeX学习笔记(数学公式编辑:公式与矩阵中符号的设置)

    1 使用 left与 right指令对公式中括号的长度进行调整 方法 将 left与 right命令分别放到公式左右括号前 这是调整括号长度前 这是调成括号长度后 2 使用 left与 right指令对公式中竖线的长度进行调整 方法 在数学
  • python怎么做多个矩阵,在python中添加两个矩阵

    I m trying to write a function that adds two matrices to pass the following doctests gt gt gt a 1 2 3 4 gt gt gt b 2 2 2
  • Java GUI,mybatis实现资产管理系统

    Java GUI 资产管理系统 前言 为了做java课设 学了一手Java GUI 感觉蛮有意思的 写写文章 做个视频记录一下 欢迎大家友善指出我的不足 资产管理系统录制视频 从头敲到尾 模块划分 资产信息管理 资产信息查询 各种条件查询

随机推荐

  • 实现一个完整的前后端交互

    题目一 计算器 1 构建项目 前端代码
  • C/C++中float和double的存储结构(转)

    在C C 中float是32位的 double是64位的 两者在内存中的存储方式和能够表示的精度均不同 目前C C 编译器标准都遵照IEEE制定的浮点数表示法来进行float double运算 无论是float还是double 在内存中的存
  • 软件测试需要学什么?软件测试技能图谱

    很多新手 不知道软件测试学习该如何开始 软件测试需要掌握哪些知识 下面是根据本人的理解 粗略整理的一个学习大纲 基本上涵盖了软件测试工程师需要掌握的全部技能 希望对刚入行或者准备学习测试的朋友提供一点指引 1 测试基础理论 不管有没有计算机
  • docker 搭建 Jenkins 容器 ,拉取git代码

    Docker 搭建 Jenkins 容器 拉取git代码 一 安装jenkins 前提条件 宿主机安装docker 1 拉取镜像 docker pull jenkins jenkins 2 查看镜像 docker images 列表中有je
  • C++ 引用作为函数返回值

    1 以引用返回函数值 定义函数时需要在函数名前加 2 用引用返回一个函数值的最大好处是 在内存中不产生被返回值的副本 引用作为返回值 必须遵守以下规则 1 不能返回局部变量的引用 主要原因是局部变量会在函数返回后被销毁 因此被返回的引用就成
  • unity音效添加

    音频资源AudioClip 播放的音频通过摄像头上的Audio Listener监听 Audio Listener有且只有一个 否则会报警告 创建一个空对象 重命名为Music Player 音频源 为其添加上Audio Souce组件 将
  • Mysql - 直接查询存储的Json字符串中的数据

    我们平时使用mysql 出于项目需求 可能需要直接将Java对象或者一个大json 直接存到表中的某个字段中 使用的时候再查出来 反序列化到对象或者一个Map中 方便我们操作 大多时候 我们可能并不需要所有的数据 只想使用这个对象或者jso
  • 详解synchronized与Lock的区别与使用

    引言 昨天在学习别人分享的面试经验时 看到Lock的使用 想起自己在上次面试也遇到了synchronized与Lock的区别与使用 于是 我整理了两者的区别和使用情况 同时 对synchronized的使用过程一些常见问题的总结 最后是参照
  • 关于easyExcel实体字段对应日期类型格式化问题

    可以写一个实体转换器来实现easyExcl中的Converter接口 可参考easyExcel官方文档中的 Alibaba Easy Excel 简单 省内存的Java解析Excel工具 读Excel
  • MATLAB实现传递函数

    1 简单的传递函数模型 num 1 10 den 1 5 4 3 2 G tf num den 2 零极点模型 KGain K 系统增益K Z 1 2 3 零点 P 4 5 6 极点 G zpk Z P KGain 3 反馈系统 G1 tf
  • 阿里马涛:重新定义云时代的开源操作系统

    作者 Just 出品 CSDN ID CSDNnews 随着云计算的发展 以及Linux平台的不断发展和生态系统的不断完善 越来越多的企业 云服务提供商都将Linux作为其数据中心的首选操作系统 不过 作为云基础设施的底座 针对云上产品和环
  • HyperLedger Fabric链码开发及测试

    https blog csdn net TripleS X article details 80550401 https blog csdn net weixin 44676392 article details 87938451 http
  • C# 实现多种语言切换,通过VS实现

    步骤 1 在要更换语言的界面 如Form1界面 选择属性 Language 选择要使用的语言 如下图 2 添加完语言之后VS会自动生成对应语言的 resx文件 通过该文件可以编辑语言 由于VS已经给我们添加了该界面的所有字段和变量 所以我们
  • 海思his35xx安防芯片音视频媒控驱动基础篇MIPI RX模块(一)

    先给自己打个广告 本人的微信公众号正式上线了 搜索 张笑生的地盘 主要关注嵌入式软件开发 股票基金定投 足球等等 希望大家多多关注 有问题可以直接留言给我 一定尽心尽力回答大家的问题 二维码如下 一 背景介绍 海思芯片的应用方向大致分为如下
  • python安装库出现retrying-Python之retrying

    retrying是一个很好用的关于重试的Python包 可以用来自动重试一些可能会运行失败的程序段 为什么选择retrying 我们在写一些程序的时候 会去调用一些外部资源 组件 这些外部程序对我们来说是不可控的 所以它们不可用 运行失败都
  • SqlServer数据库删除数据

    数据库删除数据的三种代码方式 1 删除表结构及所有数据 drop table table name 2 恢复表格出厂设置 id清空 truncate table table name 3 删除表数据 delete from table na
  • 期货怎么满仓(期货为什么不能满仓操作)

    期货满仓怎么bao cang q 您是想问期货满仓爆仓怎么处理吗 满仓交易的风险就是会强制平仓 也就是所谓的爆仓 爆仓是指 1 投资者帐户权益为负数 表明投资者不仅输光了全部保证金而且还倒欠期货经纪公司债务 2 发生爆仓时 投资者必须及时将
  • 红帽认证主要考哪些内容呢

    红帽认证考试主要考以下内容 RH124 红帽系统管理I 主要涉及访问命令行 从命令行访问文件 获取RHCEL7帮助信息 创建及查看编辑文件 管理用户和用户组 管理文件和目录权限 监视和管理Linux进程 控制服务和后台进程 管理OpenSS
  • Android自定义自动换行LinearLayout探索与实现

    Android自定义自动换行LinearLayout探索与实现 在Android开发中 我们经常需求实现一些特定的布局效果以满足用户的需求 其中之一就是自动换行布局 即当容器内的子视图数量超过一行时 自动将多余的子视图放到下一行进行显示 本
  • go语言试用标准c 库,Go语言开发(十三)、Go语言常用标准库三

    Go语言开发 十三 Go语言常用标准库三 一 sync 1 sync简介 sync提供基本的同步原语 如sync Mutex sync RWMutex sync Once sync Cond sync Waitgroup 除了Once和Wa