Go的Gin比java的Springboot更加的开箱即用?

前言

隔壁组的云计算零零后女同事,后文简称 云女士 ,非说 Go 的 Gin 框架比 Springboot 更加的开箱即用,我心想在 Java 里面 Springboot 已经打遍天下无敌手,这份底蕴岂是 Gin 能比。

但是云女士突出一个执拗,非我要 PK 一把, PK 内容就是她使用 Gin,而我使用 Springboot 快速搭建一个简单的 Crud 工程,最后让其他同事来评判哪个更开箱即用。我毫不犹豫就答应了,作为搭建 Springboot 学习工程的资深 Crud 选手,咱这份底气还是有的。

云女士选择使用 Gin + Gorm 来搭建,而我原本想选择 Springboot + MyBatis,后面转念一想,这 MyBatis 要写 XML 文件,指不定就因为这个被云女士嘲笑了,所以我把 MyBatis 替换为了 MyBatis-Plus,这就足够的简洁了吧。

正文

准备事项

既然是 Crud 工程,自然要准备好操作的表,我和云女士通过如下语句在各自的数据库中创建好了如下两张表。

CREATE TABLE people (
    id INT(11) PRIMARY KEY AUTO_INCREMENT,
    p_name VARCHAR(255) NOT NULL,
    p_age INT(11) NOT NULL
)

CREATE TABLE book (
    id INT(11) PRIMARY KEY AUTO_INCREMENT,
    b_name VARCHAR(255) NOT NULL,
    b_price FLOAT NOT NULL
)

Gin快速搭建Crud工程

云女士的工程结构如下所示。

Gin目录结构

云女士的 go.mod 文件内容如下所示。

module gobase

go 1.17

require (
    github.com/gin-gonic/gin v1.6.0
    github.com/jinzhu/gorm v1.9.16
    github.com/sirupsen/logrus v1.9.3
    github.com/spf13/cast v1.5.1
)

云女士定义了两个结构体作为模型( Model ),book.go 文件内容如下所示。

package model

const (
    BookTableName = "book"
)

type Book struct {
    ID int64 `gorm:"column:id"`
    BookName string `gorm:"column:b_name"`
    BookPrice float64 `gorm:"column:b_price"`
}

func (b *Book) TableName() string {
    return BookTableName
}

people.go 文件内容如下所示。

package model

const (
    PeopleTableName = "people"
)

type People struct {
    ID int64 `gorm:"column:id"`
    PeopleName string `gorm:"column:p_name"`
    PeopleAge int64 `gorm:"column:p_age"`
}

func (p *People) TableName() string {
    return PeopleTableName
}

云女士补充道,TableName()方法是为模型指定对应的表名。

云女士为 book 表和 people 表分别定义了 Dao 接口,dao.go 文件内容如下所示。

package dao

import "gobase/model"

type BookDao interface {
    AddBook(book *model.Book) error
    UpdateBook(book *model.Book) error
    DeleteBook(book *model.Book) error
    ListBookById(id uint) (*model.Book, error)
}

type PeopleDao interface {
    AddPeople(book *model.People) error
    UpdatePeople(book *model.People) error
    DeletePeople(book *model.People) error
    ListPeopleById(id uint) (*model.People, error)
}

BookDao 接口对应的实现在book_dao_impl.go文件中,实现如下。

package dao

import (
    "github.com/jinzhu/gorm"
    "gobase/model"
)

type BookDaoImpl struct {
    DB *gorm.DB
}

func (b *BookDaoImpl) AddBook(book *model.Book) error {
    if createResult := b.DB.Create(book); createResult.Error != nil {
        return createResult.Error
    }
    return nil
}

func (b *BookDaoImpl) UpdateBook(book *model.Book) error {
    if saveResult := b.DB.Save(book); saveResult.Error != nil {
        return saveResult.Error
    }
    return nil
}

func (b *BookDaoImpl) DeleteBook(book *model.Book) error {
    if deleteResult := b.DB.Delete(book); deleteResult.Error != nil {
        return deleteResult.Error
    }
    return nil
}

func (b *BookDaoImpl) ListBookById(id uint) (*model.Book, error) {
    var book model.Book
    if listResult := b.DB.Where("id = ?", id).First(&book); listResult.Error != nil {
        return nil, listResult.Error
    }
    return &book, nil
}

PeopleDao 接口对应的实现在people_dao_impl.go文件中,实现如下。

package dao

import (
    "github.com/jinzhu/gorm"
    "gobase/model"
)

type PeopleDaoImpl struct {
    DB *gorm.DB
}

func (b *PeopleDaoImpl) AddPeople(people *model.People) error {
    if createResult := b.DB.Create(people); createResult.Error != nil {
        return createResult.Error
    }
    return nil
}

func (b *PeopleDaoImpl) UpdatePeople(people *model.People) error {
    if saveResult := b.DB.Save(people); saveResult.Error != nil {
        return saveResult.Error
    }
    return nil
}

func (b *PeopleDaoImpl) DeletePeople(people *model.People) error {
    if deleteResult := b.DB.Delete(people); deleteResult.Error != nil {
        return deleteResult.Error
    }
    return nil
}

func (b *PeopleDaoImpl) ListPeopleById(id uint) (*model.People, error) {
    var people model.People
    if listResult := b.DB.Where("id = ?", id).First(&people); listResult.Error != nil {
        return nil, listResult.Error
    }
    return &people, nil
}

要操作数据库,肯定需要数据库连接,云女士将数据库连接的管理实现在了mysql_connection_pool.go文件中,内容如下所示。

package mysql

import (
    "fmt"
    "github.com/jinzhu/gorm"
    "gobase/dao"
    "log"
    "time"
)

const (
    UserName     = "root"
    PassWord     = "root"
    Host         = "192.168.101.8"
    Port         = 3306
    Database     = "gotest"
    MaxLifetime  = 60 * time.Second
    MaxIdletime  = 30 * time.Second
    MaxOpenconns = 6
    MaxIdleconns = 2
    Dialect      = "mysql"
)

type DataSouce struct {
    db      *gorm.DB
}

func NewDataSource() *DataSouce {
    var db *gorm.DB

    dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Asia%%2FShanghai",
            UserName, PassWord, Host, Port, Database)
    db, err := gorm.Open(Dialect, dsn)
    if err != nil {
        log.Fatal(err.Error())
    }

    db.DB().SetConnMaxLifetime(MaxLifetime)
    db.DB().SetConnMaxIdleTime(MaxIdletime)
    db.DB().SetMaxOpenConns(MaxOpenconns)
    db.DB().SetMaxOpenConns(MaxIdleconns)

    return &DataSouce{
        db: db,
    }
}

// BookDao 操作book表
func (d *DataSouce) BookDao() dao.BookDao {
    return &dao.BookDaoImpl{
        DB: d.db,
    }
}

// PeopleDao 操作people表
func (d *DataSouce) PeopleDao() dao.PeopleDao {
    return &dao.PeopleDaoImpl{
        DB: d.db,
    }
}

云女士将路由写在了webservice.go文件中,内容如下。

package adapter

import (
    "github.com/gin-gonic/gin"
    "gobase/mysql"
)

func Init() error {
    dataSouce := mysql.NewDataSource()

    bookController := NewBookController(dataSouce)
    propleController := NewPropleController(dataSouce)

    engine := gin.Default()
    routerGroupBook := engine.Group("/book")
    routerGroupBook.POST("/add", bookController.AddBook)
    routerGroupBook.POST("/update", bookController.UpdateBook)
    routerGroupBook.POST("/delete", bookController.DeleteBook)
    routerGroupBook.POST("/list", bookController.ListBookById)

    routerGroupPeople := engine.Group("/people")
    routerGroupPeople.POST("/add", propleController.AddPeople)
    routerGroupPeople.POST("/update", propleController.UpdatePeople)
    routerGroupPeople.POST("/delete", propleController.DeletePeople)
    routerGroupPeople.POST("/list", propleController.ListPeopleById)

    return engine.Run()
}

其实除了绑定路由,云女士还在Init()函数中进行了简单的服务注入,也就是创建数据库连接池,然后将数据库连接池给到对应的 web 服务。

云女士将操作 book 表对应的 web 服务写在了book_controller.go文件中,其实现如下所示。

package adapter

import (
    "github.com/gin-gonic/gin"
    "github.com/sirupsen/logrus"
    "github.com/spf13/cast"
    "gobase/model"
    "gobase/mysql"
    "net/http"
)

type BookController struct {
    dataSource *mysql.DataSouce
}

func NewBookController(dataSource *mysql.DataSouce) BookController {
    return BookController{
        dataSource: dataSource,
    }
}

func (b *BookController) AddBook(ctx *gin.Context) {
    var book model.Book
    if err := ctx.ShouldBind(&book); err != nil {
        logrus.Error("读取Book信息失败")
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    bookDao := b.dataSource.BookDao()
    err := bookDao.AddBook(&book)
    if err != nil {
        logrus.Error("添加Book失败", err)
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    ctx.JSON(http.StatusOK, gin.H{
        "message": "success",
    })
}

func (b *BookController) UpdateBook(ctx *gin.Context) {
    var book model.Book
    if err := ctx.ShouldBind(&book); err != nil {
        logrus.Error("读取Book信息失败")
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    bookDao := b.dataSource.BookDao()
    err := bookDao.UpdateBook(&book)
    if err != nil {
        logrus.Error("更新Book失败", err)
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    ctx.JSON(http.StatusOK, gin.H{
        "message": "success",
    })
}

func (b *BookController) DeleteBook(ctx *gin.Context) {
    var book model.Book
    if err := ctx.ShouldBind(&book); err != nil {
        logrus.Error("读取Book信息失败")
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    bookDao := b.dataSource.BookDao()
    err := bookDao.DeleteBook(&book)
    if err != nil {
        logrus.Error("删除Book失败", err)
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    ctx.JSON(http.StatusOK, gin.H{
        "message": "success",
    })
}

func (b *BookController) ListBookById(ctx *gin.Context) {
    id := cast.ToUint(ctx.Query("id"))
    bookDao := b.dataSource.BookDao()
    book, err := bookDao.ListBookById(id)
    if err != nil {
        logrus.Error("查询Book失败", err)
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    ctx.JSON(http.StatusOK, book)
}

云女士将操作 people 表对应的 web 服务写在了people_controller.go文件中,其实现如下所示。

package adapter

import (
    "github.com/gin-gonic/gin"
    "github.com/sirupsen/logrus"
    "github.com/spf13/cast"
    "gobase/model"
    "gobase/mysql"
    "net/http"
)

type PeopleController struct {
    dataSource *mysql.DataSouce
}

func NewPropleController(dataSource *mysql.DataSouce) PeopleController {
    return PeopleController{
        dataSource: dataSource,
    }
}

func (p *PeopleController) AddPeople(ctx *gin.Context) {
    var people model.People
    if err := ctx.ShouldBind(&people); err != nil {
        logrus.Error("读取People信息失败")
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    peopleDao := p.dataSource.PeopleDao()
    err := peopleDao.AddPeople(&people)
    if err != nil {
        logrus.Error("添加People失败", err)
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    ctx.JSON(http.StatusOK, gin.H{
        "message": "success",
    })
}

func (p *PeopleController) UpdatePeople(ctx *gin.Context) {
    var people model.People
    if err := ctx.ShouldBind(&people); err != nil {
        logrus.Error("读取People信息失败")
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    peopleDao := p.dataSource.PeopleDao()
    err := peopleDao.UpdatePeople(&people)
    if err != nil {
        logrus.Error("更新People失败", err)
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    ctx.JSON(http.StatusOK, gin.H{
        "message": "success",
    })
}

func (p *PeopleController) DeletePeople(ctx *gin.Context) {
    var people model.People
    if err := ctx.ShouldBind(&people); err != nil {
        logrus.Error("读取People信息失败")
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    peopleDao := p.dataSource.PeopleDao()
    err := peopleDao.DeletePeople(&people)
    if err != nil {
        logrus.Error("删除People失败", err)
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    ctx.JSON(http.StatusOK, gin.H{
        "message": "success",
    })
}

func (p *PeopleController) ListPeopleById(ctx *gin.Context) {
    id := cast.ToUint(ctx.Query("id"))
    peopleDao := p.dataSource.PeopleDao()
    people, err := peopleDao.ListPeopleById(id)
    if err != nil {
        logrus.Error("查询People失败", err)
        ctx.JSON(http.StatusInternalServerError, gin.H{
            "message": "failed",
        })
        return
    }
    ctx.JSON(http.StatusOK, people)
}

最后,云女士简单的展示了一下对 book 表和 prople 表的 Crud 操作。

book 表和 people 表的增删改成功时返回内容如下所示。

Gin-增删改成功

book 表和 people 表的查询成功时返回内容如下所示。

Gin-查询图书

Gin-查询人物

Spring boot 快速搭建Crud工程

Spring Boot 基础就不介绍了

云女士基于 Gin 和 Gorm 搭建的 Crud 工程,我看完后内心扑哧一笑:不过如此。

那现在该轮到我表演了。首先给出整个工程结构图如下所示。

Springboot目录结构

POM 文件内容如下所示。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.1</version>
    </parent>

    <groupId>com.lee.javabase</groupId>
    <artifactId>javabase</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.1.0</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.16</version>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
    </dependencies>

</project>

同样,定义 book 表和 people 表对应的实体类 Book 和 People,如下所示。

@Getter
@Setter
public class Book {
    @TableField("id")
    private int id;

    @TableField("b_name")
    private String bookName;
    @TableField("b_price")
    private float bookPrice;

}

@Getter
@Setter
public class People {

    @TableField("id")
    private int id;

    @TableField("p_name")
    private String peopleName;
    @TableField("p_age")
    private int peopleAge;

}

然后定义定义接口,如下所示。

@Mapper
public interface BookMapper extends BaseMapper<Book> {
}

@Mapper
public interface PeopleMapper extends BaseMapper<People> {
}

最后是对应的 Controller 实现, BookController 实现如下。

@Slf4j
@RestController
@RequestMapping("/book")
public class BookController {

    @Autowired
    private BookMapper bookMapper;

    @PostMapping("/add")
    public ResponseEntity<String> addBook(@RequestBody Book book) {
        try {
            bookMapper.insert(book);
            return new ResponseEntity<>("添加图书成功", HttpStatus.OK);
        } catch (Exception e) {
            log.error("添加图书失败", e);
            return new ResponseEntity<>("添加图书失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("/update")
    public ResponseEntity<String> updateBook(@RequestBody Book book) {
        try {
            bookMapper.updateById(book);
            return new ResponseEntity<>("更新图书成功", HttpStatus.OK);
        } catch (Exception e) {
            log.error("更新图书失败", e);
            return new ResponseEntity<>("更新图书失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("/delete")
    public ResponseEntity<String> deleteBook(@RequestParam("id") int id) {
        try {
            bookMapper.deleteById(id);
            return new ResponseEntity<>("删除图书成功", HttpStatus.OK);
        } catch (Exception e) {
            log.error("删除图书失败", e);
            return new ResponseEntity<>("删除图书失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("/list")
    public ResponseEntity<Book> listBook(@RequestParam("id") int id) {
        try {
            Book book = bookMapper.selectById(id);
            return new ResponseEntity<>(book, HttpStatus.OK);
        } catch (Exception e) {
            log.error("查询图书失败", e);
            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

PeopleController 实现如下所示。

@Slf4j
@RestController
@RequestMapping("/people")
public class PeopleController {

    @Autowired
    private PeopleMapper peopleMapper;

    @PostMapping("/add")
    public ResponseEntity<String> addPeople(@RequestBody People people) {
        try {
            peopleMapper.insert(people);
            return new ResponseEntity<>("添加人物成功", HttpStatus.OK);
        } catch (Exception e) {
            log.error("添加人物失败", e);
            return new ResponseEntity<>("添加人物失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("/update")
    public ResponseEntity<String> updatePeople(@RequestBody People people) {
        try {
            peopleMapper.updateById(people);
            return new ResponseEntity<>("更新人物成功", HttpStatus.OK);
        } catch (Exception e) {
            log.error("更新人物失败", e);
            return new ResponseEntity<>("更新人物失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("/delete")
    public ResponseEntity<String> deletePeople(@RequestParam("id") int id) {
        try {
            peopleMapper.deleteById(id);
            return new ResponseEntity<>("删除人物成功", HttpStatus.OK);
        } catch (Exception e) {
            log.error("删除人物失败", e);
            return new ResponseEntity<>("删除人物失败", HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }

    @PostMapping("/list")
    public ResponseEntity<People> listPeople(@RequestParam("id") int id) {
        try {
            People people = peopleMapper.selectById(id);
            return new ResponseEntity<>(people, HttpStatus.OK);
        } catch (Exception e) {
            log.error("查询人物失败", e);
            return new ResponseEntity<>(null, HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

启动应用程序, book 表的 Crud 操作结果如下所示。

prople 表的 Crud 操作结果如下所示。

总结

我宣布,Springboot 就是快速搭建 Crud 工程的

其实,在基于 Gin 和 Gorm 搭建 Crud 工程时,云女士还是写得复杂了一点,但是我有幸看过她们云平台的项目的代码,云女士写得也没毛病,虽然是个简化版,但也是严格遵从她们项目的代码结构来实现的。

说回 Springboot,毫无疑问,无论是天然自带 Tomcat 或 Jetty ,还是和三方框架整合的各种 Starter 包,Springboot 都将开箱即用做到了极致,但是转念又一想,其实 Springboot 和 Gin 严格来说做比较没啥意义,就像 Java 和 Go 的比较一样,我觉得也没啥意义,各自的优势区间不一样,并且各自也都在相关的领域叱咤风云。

各位看官,你们觉得呢。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【2024最新Java面试宝典】—— SpringBoot面试题(44道含答案)

1. 什么是 Spring Boot&#xff1f; Spring Boot 是 Spring 开源组织下的子项目&#xff0c;是 Spring 组件一站式解决方案&#xff0c;主要是简化了使用 Spring 的难度&#xff0c;简省了繁重的配置&#xff0c;提供了各种启动器&#xff0c;使开发者能快速上手。 2. 为什么…

【PlantUML系列】用例图(三)

目录 一、组成部分 二、典型案例 一、组成部分 参与者&#xff08;Actors&#xff09;&#xff1a;使用关键字 actor 后跟参与者的名称。用例&#xff08;Use Cases&#xff09;&#xff1a;使用关键字 usecase 后跟用例的名称和编号&#xff08;可选&#xff09;。系统边界…

C++命运石之门代码抉择:C++入门(上)

文章目录 1.前言1.1 什么是C1.2 C的发展1.3 C的重要性1.4 如何学习C1.5 C要学什么 2. C语言过渡到C(上)2.1 域2.1.1 命名空间2.1.1.1 定义2.1.1.2 作用域限定符2.1.1.3 使用 2.1.2 域的使用优先级 2.2 输入及输出2.2.1 std 命名空间及自定义命名空间2.2.2 .C输入&输出 2.3 …

Composer在安装的过程中经常找不到刚更新的包

明明有v2.1.0版本&#xff0c;安装就是找不到这个版本的包。 1. Composer 官方网址&#xff1a;https://getcomposer.org 中文网站&#xff1a;https://www.phpcomposer.com 官方文档&#xff1a;https://docs.phpcomposer.com 2. Packagist Packagist 是 Composer的组件仓库…

Android笔记【14】结合LaunchedEffect实现计时器功能。

一、问题 cy老师第五次作业 结合LaunchedEffect实现计时器功能。要求&#xff1a;动态计时&#xff0c;每秒修改时间&#xff0c;计时的时间格式为“00&#xff1a;00&#xff1a;00”&#xff08;小时&#xff1a;分钟&#xff1a;秒&#xff09;提交源代码的文本和运行截图…

【强化学习入门笔记】 2.1 值迭代

本系列为学习赵世钰老师的《强化学习的数学原理》所作的学习笔记. 本节我们将介绍强化学习中的值迭代求解方法. 2.1.1 算法步骤 在1.5节我们介绍了通过迭代可以求贝尔曼最优公式的最优解, 这个方法就叫值迭代: v k 1 max ⁡ π ∈ Π ( r π γ P π v k ) , k 0 , 1 , …

汽车车牌标记支持YOLO,COCO,VOC三种格式标记,4000张图片的数据集

本数据集支持YOLO&#xff0c;COCO&#xff0c;VOC三种格式标记汽车车牌&#xff0c;无论是新能源汽车还是油车都能识别标记&#xff0c;该数据集一共包含4000张图片 数据集分割 4000总图像数 训练组 70&#xff05; 2800图片 有效集 20&#xff05; 800图片 测…

python基础:(八)文件

目录 一.从文件中读取数据1.1读取整个文件1.2文件路劲1.3逐行读取 二.写入文件 一.从文件中读取数据 各位小伙伴&#xff0c;文件这一块得好好学&#xff0c;多看多敲代码&#xff0c;以后处理数据&#xff0c;写爬虫少不了这个&#xff0c;先从基础&#xff08;简单的&#x…

输电线路故障测距研究

故障分析法容易受到过渡电阻、故障类型等因素的影响&#xff0c;从而造成测距误差较大。 行波法不受电力系统运行方式的影响&#xff0c;得到了广泛的应用。波头信息的提取方法主要有&#xff1a;小波变换、希尔伯特黄变换、TT变换等。 智能测距法逐渐被应用于输电线路故障测…

FPGA实战篇(IP核之MMCM/PLL实验)

1.MMCM/PLL IP 核简介 锁相环作为一种反馈控制电路&#xff0c;其特点是利用外部输入的参考信号控制环路内部震荡信号的频率和相位。因为锁相环可以实现输出信号频率对输入信号频率的自动跟踪&#xff0c;所以锁相环通常用于闭环跟踪电路。 锁相环在工作的过程中&#xff0c;当…

wordpress网站安装了Linux宝塔面板,限制IP地址访问网站,只能使用域名访问网站

一、Linux服务器安装Linux宝塔面板 这个步骤参考网上其他教程。 二、Linux宝塔面板部署wordpress网站 这个步骤参考网上其他教程&#xff0c;保证网站能够正常访问&#xff0c;并且使用Linux宝塔面板申请并部署了SSL证书&#xff0c;使用https协议默认443端口正常访问。 三…

顶顶通电话机器人开发接口对接大语言模型之实时流TTS对接介绍

大语言模型一般都是流式返回文字&#xff0c;如果等全部文字返回了一次性去TTS&#xff0c;那么延迟会非常严重&#xff0c;常用的方法就是通过标点符号断句&#xff0c;返回了一句话就提交给TTS。随着流TTS的出现&#xff0c;就可以直接把大模型返回的文字灌给流TTS&#xff0…

leetcode每日一题(20241210)

leetcode每日一题&#xff08;20241210&#xff09;今天依旧是棋盘类型的题目&#xff0c;但是今天的只是表面相关&#xff0c;看题&#xff1a; 935.骑士拨号器 题目描述&#xff1a; 象棋骑士有一个独特的移动方式&#xff0c;它可以垂直移动两个方格&#xff0c;水平移动一…

记录ubuntu22.04重启以后无法获取IP地址的问题处理方案

现象描述&#xff1a;我的虚拟机网络设置为桥接模式&#xff0c;输入ifconfig只显示127.0.0.1&#xff0c;不能连上外网。&#xff0c;且无法上网&#xff0c;用ifconfig只有如下显示&#xff1a; 1、sudo -i切换为root用户 2、输入dhclient -v 再输入ifconfig就可以看到多了…

MVC基础——市场管理系统(一)

文章目录 项目地址一、创建项目结构1.1 创建程序以及Controller1.2 创建View1.3 创建Models层,并且在Edit页面显示1.4 创建Layou模板页面1.5 创建静态文件css中间件二、Categories的CRUD2.1 使用静态仓库存储数据2.2 将Categorie的列表显示在页面中(List)2.3 创建_ViewImport.…

strncpy在复制含有多个\0的字符串时遇到的问题

strncpy在复制含有多个\0的字符串的时候&#xff0c;会产生截断&#xff0c;因为strncpy在读取源字符串的时候&#xff0c;遇到了\0&#xff0c;函数会认为该字符串已经结束了&#xff0c;然后会向目标字符串内填充\0。 char buffer[100] "ak\0jl";for (int i 0; i…

C# 网络编程--基础核心内容

在现今软件开发中&#xff0c;网络编程是非常重要的一部分&#xff0c;本文简要介绍下网络编程的概念和实践。 C#网络编程的主要内容包括以下几个方面‌&#xff1a; : 上图引用大佬的图&#xff0c;大家也关注一下&#xff0c;有技术有品质&#xff0c;有国有家&#xff0c;情…

驱动---1.DAC8552实现三角波输出

最近开始进行新项目的研发&#xff0c;考虑用DAC做一个前级输出&#xff0c;选择了DAC8552这个器件的一个模块&#xff0c;用了野火的指南者做主控&#xff0c;芯片是STM32F103VET6&#xff0c;主频是72MHz。 一、器件手册重要信息提取 1.DAC8552具有十六位的分辨率、双通道输…

Elasticsearch入门之HTTP基础操作

RESTful REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。Web 应用程序最重要的 REST 原则是&#xff0c;客户端和服务器之间的交互在请求之间是无状态的。从客户端到服务器的每个请求都必须包含理解请求所必需的信息。如果服务器在…

计算机启动过程 | Linux 启动流程

注&#xff1a;本文为“计算机启动、 Linux 启动”相关文章合辑。 替换引文部分不清晰的图。 探索计算机的启动过程 Aleksandr Goncharov 2023/04/21 很多人对计算机的启动方式很感兴趣。只要设备开启&#xff0c;这就是魔法开始和持续的地方。在本文中&#xff0c;我们将概…