Gin的学习

在当前项目

go mod init xxx (xxx根据具体项目更改)
go get -u github.com/gin-gonic/gin

快速入门

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()

    r.GET("hello", func(context *gin.Context) {
        context.JSON(http.StatusOK,gin.H{
            //定义的数据
            "message":"gin快速入门",
        })
    })
    r.Run()
}

r.Run():参数是端口号,默认8080

RESTFUl Api

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()

    //get

    r.GET("/student", func(context *gin.Context) {
        context.JSON(http.StatusOK,gin.H{
            "message":"查询学生信息",
        })
    })

    //post

    r.POST("create_student", func(context *gin.Context) {
        context.JSON(http.StatusOK,gin.H{
            "message":"创建学生信息",
        })
    })


    r.PUT("update_student", func(context *gin.Context) {
        context.JSON(http.StatusOK,gin.H{
            "message":"修改学生信息",
        })
    })

    r.DELETE("delete_student", func(context *gin.Context) {
        context.JSON(http.StatusOK,gin.H{
            "message":"删除学生信息",
        })
    })

    r.Run()
}

访问文件

StaticFile(路径1,路径2)

路径1:是url请求的路径,路径2是文件所在的路径,另外go中没有相对路径的概念

func main() {
    r := gin.Default()
    r.StaticFile("/scene","./static/a.jpg")
    r.Run()
}

请求方式:
Get : http://127.0.0.1:8080/scene

html渲染

templates文件夹下创建html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>
        账号是:{{.name}}
    </h1>
    <h1>
        密码是:{{.pwd}}
    </h1>
</body>
</html>

注意上面要渲染的数据格式

package main

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()
    r.LoadHTMLGlob("./templates/*")

    r.GET("/index", func(context *gin.Context) {
        context.HTML(http.StatusOK,"index.html",gin.H{
            "name":"小白",
            "pwd":"123456",
        })
    })
    r.Run()
}

获取url的参数

c *gin.Context : c.Query(变量名)

注意:r.Run(":8081") 或 r.Run("127.0.0.1:8081")

如果只写端口,需要带冒号

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {

    r := gin.Default()
    r.LoadHTMLGlob("./templates/*")
    r.GET("/queryParam", func(c *gin.Context) {
        name:=c.Query("name")
        password:=c.Query("password")
        fmt.Printf("name is %s ,pwd is %s",name,password)
        c.HTML(http.StatusOK,"index.html",gin.H{
            "name": name,
            "pwd":password,
        })
    })
    r.Run(":8081")
}

postForm表单参数

PostForm(变量名)

获取表单参数

PostFormArray(变量名)

获取相同变量的值,返回一个数组

DefaultPostForm(变量名,默认值)

当没传递该变量名,设置该变量的值为参数2的值

MultipartForm()

参数为图片或文件

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)

func _form(c *gin.Context)  {
    name := c.PostForm("name")
    nameArr := c.PostFormArray("name") //可以接收name参数,合并为一个数组
    pwd := c.PostForm("pwd")
    addr := c.DefaultPostForm("addr", "广东省") //如果没传addr,设置默认值为"广东省",参数2位默认值
    picture, _ := c.MultipartForm() //参数是文件
    fmt.Printf("name is %v, pwd is %v\n",name,pwd)
    c.JSON(http.StatusOK,gin.H{
        "name":name,
        "pwd":pwd,
        "nameArr":nameArr,
        "addr":addr,
        "picture":picture,
    })
}


func main() {
    r := gin.Default()
    r.POST("/index", _form)
    r.Run()
}

请求内容

返回

{
    "addr": "普宁市",
    "name": "哈哈",
    "nameArr": [
        "哈哈",
        "小王"
    ],
    "picture": {
        "Value": {
            "addr": [
                "普宁市"
            ],
            "name": [
                "哈哈",
                "小王"
            ],
            "pwd": [
                "123abc"
            ]
        },
        "File": {
            "picture": [
                {
                    "Filename": "a.jpg",
                    "Header": {
                        "Content-Disposition": [
                            "form-data; name=\"picture\"; filename=\"a.jpg\""
                        ],
                        "Content-Type": [
                            "image/jpeg"
                        ]
                    },
                    "Size": 151263
                }
            ]
        }
    },
    "pwd": "123abc"
}

原始参数

GetRawData()


func _row(c *gin.Context) {
    data, err := c.GetRawData()
    if err == nil {
        fmt.Printf(string(data))
    }
}

func main() {
    r := gin.Default()
    r.POST("/index", _form)

    r.POST("/rawData",_row)
    r.Run()
}

请求方式一: form-data

打印结果

----------------------------859145593602517325033109
Content-Disposition: form-data; name="name"

哈哈
----------------------------859145593602517325033109
Content-Disposition: form-data; name="pwd"

123abc
----------------------------859145593602517325033109
Content-Disposition: form-data; name="name"

小王
----------------------------859145593602517325033109
Content-Disposition: form-data; name="addr"

普宁市
----------------------------859145593602517325033109--

请求方式二:x-www-form-urlencoded

打印结果:各参数之间用&拼接

name=123&pwd=abc&addr=%!E(MISSING)5%!C(MISSING)%E4%!B(MISSING)A%!A(MISSING)C

请求方式三:json

{
"name":"小明",
"age":15
}

GetHeader(xxx):获取请求头

func _row(c *gin.Context) {
    data, err := c.GetRawData()
    if err == nil {
        fmt.Println(string(data))
    }
    contentType := c.GetHeader("Content-Type")
    switch contentType {
    case "application/json":
        type User struct{
            Name string `json:"name"`
            Age int `json:"age"`
        }
        var user User
        err := json.Unmarshal(data, &user)
        if err!=nil{
            fmt.Println("异常")
        }
        fmt.Println("user:",user)
    default:
        return
    }

}

func main() {
    r := gin.Default()
    r.POST("/index", _form)

    r.POST("/rawData",_row)
    r.Run()
}

打印结果:

{

"name":"小明",

"age":15

}

user: {小明 15}

封装一个解析json到结构体的函数


func _row(c *gin.Context) {
    type User struct{
        Name string `json:"name"`
        Age int `json:"age"`
        Addr string `json:"addr"`
    }
    var user User
    err := bindJson(c, &user)
    if err!=nil {
        fmt.Println("异常")
    }
    fmt.Println(user)
}

func main() {
    r := gin.Default()
    r.POST("/index", _form)

    r.POST("/rawData",_row)
    
    r.Run()
}



func bindJson(c *gin.Context ,obj any) (err  error){
    data, err := c.GetRawData()
    contentType := c.GetHeader("Content-Type")
    switch contentType {
    case "application/json":
        err := json.Unmarshal(data, &obj)
        if err!=nil{
            fmt.Println("异常")
        }
    default:
        return  nil
    }
    return nil
}

参数绑定

shouldBind

可以绑定json、query、param、yaml、xml,如果校验不通过会返回错误

shouldBindJSON

import (
    "github.com/gin-gonic/gin"
    "net/http"
)

type student struct {
    Name string `json:"name"`
    Age int `json:"age"`
    Addr string `json:"addr"`
}
func main() {

    r := gin.Default()

    r.POST("/bind",_bindJson)

    r.Run(":8081")
}

func _bindJson(c *gin.Context) {

    var stu student
    err := c.ShouldBindJSON(&stu)
    if err!=nil {
        c.JSON(404,"发生错误")
        return
    }
    c.JSON(http.StatusOK,stu)
}

将请求体的数据绑定到结构体上,也就是类似Java的@RequestBody与bean之间的映射

ShouldBindQuery

url的参数绑定

如下:结构体每个属性的 form

代码中用的是 ShouldBindQuery,也可以用ShouldBind


type student struct {
    Name string `json:"name" form:"name"`
    Age string `json:"age" form:"age"`
    Addr string `json:"addr" form:"addr"`
}
func main() {

    r := gin.Default()

    r.GET("/bind",_bindJson)

    r.Run()
}

func _bindJson(c *gin.Context) {

    var stu student
    err := c.ShouldBindQuery(&stu)
    if err != nil {
        c.JSON(http.StatusBadGateway, gin.H{
            "error": err.Error(),
        })
    }
    c.JSON(http.StatusOK,stu)
}

ShouldBindUri

注意以下的结构体的属性中添加的 uri

以及

r.POST("/bind/:name/:age/:addr",_bindJson)


type student struct {
    Name string `uri:"name"`
    Age string `uri:"age" `
    Addr string `uri:"addr"`
}
func main() {

    r := gin.Default()

    r.POST("/bind/:name/:age/:addr",_bindJson)

    r.Run()
}

func _bindJson(c *gin.Context) {

    var stu student
    err := c.ShouldBindUri(&stu)
    if err != nil {
        c.JSON(http.StatusBadGateway, gin.H{
            "error": err.Error(),
        })
    }
    c.JSON(http.StatusOK,stu)
}

日期验证:2006-01-02 15:04:05

文件上传

file, _ := c.FormFile("file") //参数是文件传递的的变量名

c.SaveUploadedFile(file,"./upload/"+filename) :参数2为存储的文件路径

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r :=gin.Default()
    r.POST("/upload", func(c *gin.Context) {
        file, _ := c.FormFile("file")
        filename := file.Filename
        size := file.Size
        fmt.Printf("filename is  %s,size is %d\n",filename,size/1024)
        c.SaveUploadedFile(file,"./upload/"+filename)
        c.JSON(http.StatusOK,"上传成功")
    })
    r.Run()
}

文件读取

func main() {
    r :=gin.Default()
    r.POST("/upload", func(c *gin.Context) {
        file, _ := c.FormFile("file")
        read_open, _ := file.Open()
        data, _ := io.ReadAll(read_open)
        fmt.Println(string(data))
        c.JSON(http.StatusOK,string(data))
    })
    r.Run()
}

copy文件

这里我copy的是图片

create_file, _ := os.Create("./upload/1.jpg") //创建的文件
defer create_file.Close()
io.Copy(create_file,read_open) //复制
func main() {
    r :=gin.Default()
    r.POST("/upload", func(c *gin.Context) {
        file, _ := c.FormFile("file")
        read_open, _ := file.Open()
        create_file, _ := os.Create("./upload/1.jpg")
        defer create_file.Close()
        io.Copy(create_file,read_open)
        c.JSON(http.StatusOK,"上传成功")
    })
    r.Run()
}

多文件上传


func main() {
    r :=gin.Default()
    r.POST("/uploads", func(c *gin.Context) {
        form, _ := c.MultipartForm()
        files := form.File["files"] //变量名
        for _, file := range files {
            c.SaveUploadedFile(file,"./upload/"+file.Filename)
        }
        c.JSON(http.StatusOK,len(files))
    })
    r.Run()
}

文件下载

func main() {
    r :=gin.Default()
    r.GET("/download", func(c *gin.Context) {
        //唤醒浏览器下载
        c.Header("Content-Type","application/octet-stream")
        c.Header("Content-Disposition","attachment;filename="+"冰墩墩.jpg")
        c.File("upload/a.jpg")
    })
    r.Run()
}

前后端模式下的文件下载

如果是前后端模式下,后端就只需要响应一个文件数据

文件名和其他信息就写在请求头中

c.Header("fileName","xxx .png")
c .Header( "msg","文件下载成功“)
c.File("uploads/12 .png")

前端写法

async downloadFile(row) {
    this.$http({
        method: 'post'
        url:'file/upload'
        data:postData,
        responseType:"blob"
    ).then(res = > {
        const _res = res.data
        let blob = new Blob([_res], {
            type: 'application/png;
            let downloadElement = document.createElement("a");
                let href = window.URL.createobjectURL(blob); //创建下载的链接
                downloadElement.href = href.downloadElement.download = res.headers["fileName"]; //下载后文件名
                document.body.appendChild(downloadElement); downloadElement.click(); //点击下载
                document.body.removeChild(downloadElement); //下载完成移除元素
                window.URL.revokeObjectURL(href): //释放掉blob对象
        })
}

Abort() 后面的中间件不会执行

Next()方法, 多个中间件 next()之前的代码 按顺序执行,next()之后的代码 按中间件逆序执行

全局中间件 Use()

func  m1 (c *gin.Context)  {
    fmt.Println("m1 .. in")
    c.Abort()
    fmt.Println("m1 .. out")
}
func main() {
    r := gin.Default()

    r.Use(m1)
    r.GET("/m1", func(c *gin.Context) {
        fmt.Println(" c  in")
        c.JSON(200,"好")
    })
    r.Run()
}

打印结果:

m1 .. in
m1 .. out

可以看出,

Abort()对本身中间件没影响。

中间件传值

set(key)

get(key)

type user struct {
    Name string
    Age int
}
func  m1 (c *gin.Context)  {
    var user = user{"tom",10}
    c.Set("user",user)
}
func main() {
    r := gin.Default()

    r.Use(m1)
    r.GET("/m1", func(c *gin.Context) {
        _user, _ := c.Get("user")

        fmt.Println(_user)
        //_user.Name 必须断言转成对应对象才可以这样使用
        u := _user.(user)
        fmt.Println(u.Name)
        c.JSON(200,_user)
    })
    r.Run()
}

路由分组

Group(),括号里面的路径为访问的前缀

注意:如果返回的Resp里面的属性小写开头,则表示为私有的,响应时没有该属性。

type Resp struct {
    Code int `json:"code"`
    Data any `json:"data"`
    Msg string `json:"msg"`
}
type Article struct {
    Article string `json:"article"`
    Content string `json:"content"`
}

func userView(c *gin.Context)  {
    var userList []User = []User{
        {"tom",10},
        {"amy",20},
    }
    var res = Resp{200,userList,"成功"}
    fmt.Println(res)
    c.JSON(200,res)
}
func articleView(c *gin.Context)  {
    var articleList []Article = []Article{
        {"骆驼祥子","小说"},
        {"星落凝成糖","电视剧"},
    }
    c.JSON(http.StatusOK,Resp{http.StatusOK,articleList,"成功"})
}

func main() {
    r := gin.Default()

    api := r.Group("/api")
    api.GET("/user",userView)

    api2 := r.Group("article")
    api2.GET("/article",articleView)
    r.Run()
}

注意:

路由校验权限

type Resp struct {
    Code int `json:"code"`
    Data any `json:"data"`
    Msg string `json:"msg"`
}

type User struct {
    Name string `json:"name"`
    Age int `json:"age"`
}



func userView(c *gin.Context)  {
    var userList []User = []User{
        {"tom",10},
        {"amy",20},
    }
    var res = Resp{200,userList,"成功"}
    fmt.Println(res)
    c.JSON(200,res)
}

func check_token(c *gin.Context){
    token := c.GetHeader("token")
    if token !="1234"{
        c.JSON(404,Resp{400,nil,"权限校验失败"})
        c.Abort() //拦截后续操作
    }
    c.Next()
    return
}

func userInit(r *gin.RouterGroup)  {
    api := r.Group("/user_manager").Use(check_token)
    api.GET("/user",userView)
}
func main() {
    r := gin.Default()
    api := r.Group("/api")
    userInit(api)
    api.GET("/login", func(c *gin.Context) {
        c.JSON(200,"欢迎来到登录页面")
    })
    r.Run()
}

http://127.0.0.1:8080/api/user_manager/user 请求头带token=1234 能访问

因为上述代码使用了 api := r.Group("/user_manager").Use(check_token)

使用闭包的写法


func check_token(msg string)  gin.HandlerFunc{
    return func(c *gin.Context) {
        token := c.GetHeader("token")
        if token != "1234" {
            c.JSON(404, Resp{400, nil, msg})
            c.Abort() //拦截后续操作
        }
        c.Next()
        return
    }
}

func userInit(r *gin.RouterGroup)  {
    api := r.Group("/user_manager").Use(check_token("权限校验失败"))
    api.GET("/user",userView)
}

修改日志样式


func LogFormatterParams(params gin.LogFormatterParams) string {
    return fmt.Sprintf(
        "[beichen] %s |%s %d %s| %s %s %s  %s \n",
        params.TimeStamp.Format( "206-01-02 15:04:05"),
        params.StatusCodeColor(),params.StatusCode, params.ResetColor(),
        params.MethodColor(),params.Method,params.ResetColor(),
        params.Path,)
}

func main() {
    gin.SetMode(gin.ReleaseMode)
    r := gin.New()

    r.Use(gin.LoggerWithFormatter(LogFormatterParams))

    r.GET("/index")

    r.Run()
}

logrus

下载:

go get github.com/sirupsen/logrus

修改日志级别

logrus.SetLevel(logrus.DebugLevel)//修改日志级别

日志级别有

PanicLevel Level = iota
    // FatalLevel level. Logs and then calls `logger.Exit(1)`. It will exit even if the
    // logging level is set to Panic.
    FatalLevel
    // ErrorLevel level. Logs. Used for errors that should definitely be noted.
    // Commonly used for hooks to send errors to an error tracking service.
    ErrorLevel
    // WarnLevel level. Non-critical entries that deserve eyes.
    WarnLevel
    // InfoLevel level. General operational entries about what's going on inside the
    // application.
    InfoLevel
    // DebugLevel level. Usually only enabled when debugging. Very verbose logging.
    DebugLevel
    // TraceLevel level. Designates finer-grained informational events than the Debug.
    TraceLevel

将日志打印到log文件

func main() {

    file, _ := os.OpenFile( "a.log",os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
    logrus.SetOutput(file)
    logrus.SetLevel(logrus.DebugLevel)//修改日志级别
    logrus.Error("出错了")
    logrus.Warnln("警告")
    logrus.Infof("输出")
    logrus.Debugf("调试")
    logrus.Println("打印")

    fmt.Println(logrus.GetLevel())
}

同时输出到console和文件

logrus.SetOutput(io.MultiWriter(file,os.Stdout))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ava实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),可运行高分资源 Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现的毕业设计&&课程设计(包含运行文档+数据库+前后端代码),Java实现
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值