【Docker】前后端分离项目 Gin+Vue 容器化部署 | docker-compose 部署 | 部署 nginx 通过域名访问

文章目录

  • 前言
    • 前后端不完全独立
      • docker 部署
        • mysql
        • redis
        • rbac
      • docker compose 部署
      • 部署 nginx
    • 前后端独立部署

前言

项目地址:https://gitee.com/Cauchy_AQ/rbac

项目前端使用 vue3 并且由 vite 构建,后端采用 gin 框架,搭建了一个简易的权限管理系统(rbac)。本节对该项目进行容器化部署。

前后端不完全独立

代码地址:https://gitee.com/Cauchy_AQ/rbac/tree/master/

前后端部署不完全独立,指通过 vue 的 build 构建后,返回一个静态页面 index.html,然后将构建后的文件放置后端项目中,并由后端返回该页面。

docker 部署

由于项目需要使用 mysql 和 redis 两个数据库,所以除了本体项目会使用一个 docker 镜像构建,数据库也会分别独立使用 docker 容器部署。

mysql

在后端项目中,mysql 的配置如下:

mysql:
  host: mysql57
  port: 3306
  user: root
  password: root
  db: wms
  max_open_conns: 100
  max_idle_conns: 20

指定 mysql 的主机名是 mysql57,端口 3306,用户 root,密码 root,数据库 wms。

除了上述配置外,项目还需要初始化构建数据,sql 文件在后端项目中有,需要在构建 mysql 镜像时一并导入执行数据库的初始化工作。

在这里插入图片描述

如上图,在本地 /home/cauchy/docker/mysql 文件夹下,将后端项目中的 sql 文件拷贝过来 rbac.sql,并且编写 Dockerfiler 文件:

FROM mysql:5.7
COPY rbac.sql /docker-entrypoint-initdb.d/

容器内目录 /docker-entrypoint-initdb.d/ 下的 .sql 文件会被检测到,并自动执行。所以在构建镜像时,将 sql 文件拷贝至该目录下。

docker build -t mysql57:1.0 .
docker run -itd -v /home/cauchy/docker/mysql/data:/var/lib/mysql --name mysql57 -e MYSQL_ROOT_PASSWORD=root --network rbac mysql57:1.0

执行上述语句构建 mysql57:1.0 镜像,并且 -v 将容器的 /var/lib/mysql 目录挂载到本地 data 目录,--name 指定运行容器名称 mysql57,-e MYSQL_ROOT_PASSWORD=root 指定 root 用户的密码,--network 指定容器关联的网络 rbac。

三个容器会绑定在同一个网络 rbac,用于网络通信,这样在项目容器中的配置文件指定 mysql 的 host 时,使用 mysql57 就能成功发现容器并正常通信了。

如果上述执行失败,可先创建网络:docker network create rbac,再去执行上述 shell 指令。


redis

项目中使用的 redis 配置如下:

redis:
  host: redis7
  port: 6379
  password: redis
  db: 0

指定 redis 主机名是 redis7,端口 6379,密码 redis,数据库 0。

同理构建 redis:

docker run -itd -v /home/cauchy/docker/redis/data:/data --network rbac --name redis7 redis:7.0 --requirepass redis

直接采用拉取的 redis:7.0 镜像构建 redis7 容器,--requirepass 指定需要认证的密码,容器的 /data 目录挂载到本地 data 目录。

如果没有镜像,可先拉取镜像:docker pull redis:7.0,再去执行上述 shell 指令。


rbac

该项目在部署前还需调整一下相关配置:

  1. 前端构建
  • vite.config.ts 文件调整
server: {
	 // 监听地址
	 host: "127.0.0.1",
	 // 端口号
	 port: 80,
	 // 服务启动时是否自动打开浏览器
	 open: true,
	 // 允许跨域
	 cors: true,
	 // 自定义代理规则
	 proxy: {},
}

修改 host 为服务器的 ip 地址

  • .env.development 文件调整
ENV = 'development'
VITE_APP_BASE_URL = 'http://127.0.0.1:8080'

修改 VITE_APP_BASE_URL 为后续实际访问服务的 url,即 http://服务器ip:服务监听端口,本项目配置端口在 conf/conf.yaml 中是 8080

  • npm run build 构建前端项目

构建成功后会生成一个 dist 目录,直接拷贝到后端的 static 目录下。

  1. 后端返回

在后端中,routers/routers.go 添加如下代码:

r.LoadHTMLGlob("static/dist/*.html")
r.Static("/assets", "./static/dist/assets")

r.GET("/", func(c *gin.Context) {
	if strings.HasSuffix(c.Request.RequestURI,".js") {
	        c.Header("Content-Type", "application/javascript; charset=utf-8")
	} else {
	        c.Header("Content-Type", "text/html; charset=utf-8")
	}
	c.HTML(http.StatusOK, "index.html", nil)
})

r.NoRoute(func(c *gin.Context) {
	if strings.HasSuffix(c.Request.RequestURI, ".js") {
		c.Header("Content-Type", "application/javascript; charset=utf-8")
	} else {
		c.Header("Content-Type", "text/html; charset=utf-8")
	}
	c.HTML(http.StatusOK, "index.html", nil)
})

LoadHTMLGlob 加载静态页面,Static 指定访问静态文件 js、css 时去哪个实际目录访问,GET("/", ...) 所有访问都会返回 index.html 页面,NoRoute 路由不存在时也返回 index.html 页面。由于获取前端界面需要 http 请求发给后端,后端会返回对应的资源文件,即上述的 js、css 文件,那么这些上行的路由在实际的路由中是不存在的,所以在此需要指定不存在路由是也同样返回界面,而不是报错。


对源码做上述修改后,就可以来构建基础镜像了。

后端的源码上传到服务器 /home/cauchy/docker/rbac 上:

在这里插入图片描述

编写 Dockerfile 文件:

FROM golang:1.22-alpine AS builder

ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

WORKDIR /build

COPY . .

RUN go mod tidy
RUN go build -o rbac .


FROM scratch

WORKDIR /app

COPY ./conf /app/conf
COPY ./static /app/static
COPY --from=builder /build/rbac .

ENTRYPOINT ["/app/rbac"]

这里采用分阶段构建,实际运行仅需要一个二进制文件和相关配置文件。

先拉取 golang:1.22-alpine 镜像提供 go 的基础环境,ENV 中指定了程序需要的的环境变量,WORKDIR 指定工作目录,COPY 拷贝当前宿主机 Dockerfile 文件所在的同级所有文件到容器中工作目录下 /buildRUN 执行构建 gin 项目的指令,最终生成一个二进制文件 rbac。接下来拉取 scratch 镜像作为最终运行程序的环境,拷贝上一个容器中的二进制文件 rbac,源码下的配置文件夹 conf,前端构建后的文件夹 static,到这个小镜像的工作目录下,然后 ENTRYPOINT 指定执行这个二进制文件即可。

执行构建指令:

docker build -t rbac:1.0 .
docker run -itd -p 8080:8080 --network rbac --name rbac rbac:1.0

创建 rbac:1.0 镜像,构建容器 rbac,开放宿端口 8080 映射为容器内的 8080 端口。(服务器需要放行这个端口)

至此,三个 docker 容器,依此部署,成功部署该项目。

在这里插入图片描述


docker compose 部署

使用 docker compose 管理编排多个容器,按照依赖顺序构建容器服务。

首先需要在项目源码(后端)中添加新文件:docker-compose.yml,并编写如下内容:

version: "3.8"

services:

  mysql57:
    #build:
    #  context: ../mysql/
    #  dockerfile: Dockerfile
    image: mysql:5.7
    environment:
      - "MYSQL_ROOT_PASSWORD=root"
    volumes:
      - mysqlData:/var/lib/mysql
      - ./rbac.sql:/docker-entrypoint-initdb.d/rbac.sql
    networks:
      - rbac
    restart: always

  redis7:
    image: redis:7.0
    command: redis-server --requirepass redis
    restart: always
    volumes:
      - redisData:/data
    networks:
      - rbac

  rbac:
    build: ./
    command: sh -c "sleep 10; ./wait-for.sh mysql57:3306 redis7:6379 -- ./rbac"
    restart: on-failure
    ports:
      - "8080:8080"
    depends_on:
      - mysql57
      - redis7
    networks:
      - rbac


networks:
  rbac:

volumes:
  mysqlData:
  redisData:

详细的 docker compose 模板文件可参考:https://vuepress.mirror.docker-practice.com/compose/

上述文件详细说明:

  • version:当前 docker compose file 的版本,可以查看 docker 引擎的版本(docker compose version),然后对照该表 这里,一般默认 3.8 即可
  • services:描述一组服务,必须写
  • build:在启动容器之前,根据 Dockerfile 构建镜像, 然后根据构建的镜像启动容器。该命令下的 context 指定 Dockerfile 所在的上下文目录位置
  • mysql57redis7rbac:都代表服务的名称,docker-compose 文件中服务名称都是唯一的。要指定容器的名称,可以使用 container_name 模板命令,指定特定名称,每个服务器容器名称唯一
  • image:指定启动容器使用的镜像
  • environment:给容器启动指定环境变量,env_file 模板命令也可以指定某个文件作为环境变量载入
  • volumes:指定宿主机与容器目录或文件的映射,但是在 docker compose 中不会主动创建未存在的目录,可以通过上述代码中最后的声明命令声明要挂载的目录
  • networks:指定启动容器使用网桥,同样未存在的 network 也需要声明
  • restart:指定当前容器的重启策略,always 表示总是运行,on-failure 表示失败后重启,详细可参考 这里
  • command:覆盖容器启动后默认执行的命令
  • depends_on:服务启动依赖的其他服务,但是当前服务不会等待依赖的服务完全启动之后才启动
  • ports:宿主机和容器的端口映射

可以看到,rbac 服务 command 命令中使用了 sleep 10; 还用了 ./wait-for.sh。按理执行这个脚本文件,会在启动 rbac 容器前先启动好 mysql、redis,但是我不知道为什么行不通,所以索性强制休眠 10 秒,等待另两个服务完成构建。

这个脚本文件参考:https://github.com/Eficode/wait-for,用于解决上述 depends_on 遗留的问题,帮助服务更好的完成按依赖顺序构建。

当然执行完这个 docker-compose.yml 文件,如配置中所示会构建一个新镜像,rbac 服务中 build: ./,即会在当前同级目录下找到 Dockerfile 文件构建,我们重新来看一下这个文件。当前目录文件如下所示:

在这里插入图片描述

Dockerfile:与之前分步构建时大致相同,不过换了一个镜像(不是 scratch 这个小镜像了),因为 wait-for.sh 脚本文件需要依赖 netcat,需要借助 apt-get 环境下载。(前面说了,我没使用成功,不能正常的等待依赖服务执行,所以如果不想使用的也可以换个能正常执行 sleep 的小镜像就行,不必用 ubuntu:latest 这个偏大的镜像)

FROM golang:1.22-alpine AS builder

ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

WORKDIR /build

COPY . .

RUN go mod tidy
RUN go build -o rbac .


FROM ubuntu:latest

WORKDIR /app

COPY ./wait-for.sh .
COPY ./conf /app/conf
COPY ./static /app/static
COPY --from=builder /build/rbac .

RUN set -eux; \
    apt-get update; \
    apt-get install -y \
        --no-install-recommends \
        netcat; \
        chmod 755 wait-for.sh;

# ENTRYPOINT ["/app/rbac"]

注释 # ENTRYPOINT ["/app/rbac"],因为在 docker-compose.yml 中执行完 sleep 命令后,会去执行这个二进制文件,注意到文件中的 -- ./rbac

至此,通过 docker compose 部署本项目也成功了。


部署 nginx

由于要通过域名访问后端项目地址,那么可以通过加一个 nginx 容器,做一层正向代理。

第一步首先要进行域名解析:

  • 服务器的管理后台添加域名解析

在这里插入图片描述

  • 域名管理解析网站主机 IP

在这里插入图片描述

  • 防火墙开放 80 端口:
sudo apt install firewalld
sudo firewall-cmd --zone=public --add-port=80/tcp --permanent
sudo firewall-cmd --reload

docker-compose.yml 中添加一个 nginx 镜像:

nginx125:
  image: nginx:1.25-alpine
  ports:
    - "80:80"
  networks:
    - rbac
  volumes:
    - ./nginx.conf:/etc/nginx/nginx.conf

nginx.conf 配置如下:

user root;

worker_processes  2;

error_log /error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://172.18.0.5:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header REMOTE-HOST $remote_addr;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_redirect off;
        }
    }
}

这里域名 server_name 自行更换,proxy_pass 代理地址这里使用 docker inspect xxx 查看 rbac 这个 docker 的 ip,若换成自己的服务器 ip 或 localhost 也许也行,自行实验。

重新一键部署 docker compose up 即可通过域名访问,或是直接使用服务器 ip 访问。


前后端独立部署

代码地址:https://gitee.com/Cauchy_AQ/rbac/tree/rbac/

前面部署是通过后端程序返回前端静态页面完成的,也可在不修改源代码的情况下(之前部署需要在后端添加返回前端界面的代码),独立部署前后端,并且也通过 docker-compose.yml 一键部署。

在前端 frontend 文件夹下,需要自行修改 .env.developmentvite.config.ts,并且添加 Dockerfile 和一个 nginx.conf 文件。

  • .env.development:配置后端的地址 VITE_APP_BASE_URL = http://121.xxx.xxx.7:8080,后端 ip + 监听的端口
  • vite.config.tsserver 模块配置 host 为后端主机地址

nginx.conf

user root;

worker_processes  4;

error_log /error.log;

events {
    worker_connections 1024;
}

http {
    server {
        listen 80;
        server_name example.com;

		root /usr/share/nginx/html;
		index index.html index.htm;
	
		include mime.types;
		default_type  application/octet-stream;
	
		location / {
		    try_files $uri $uri/ /index.html;	
		}
	
		location /assets/ {
	    	    alias /usr/share/nginx/html/assets/;
	    	    expires 1h;
		}
	
	    location ^~ /api/ {
	        proxy_pass http://121.xxx.xxx.7:8080;
	        proxy_set_header Host $host;
	        proxy_set_header X-Real-IP $remote_addr;
	        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
	        proxy_set_header REMOTE-HOST $remote_addr;
	    }
    }
}

Dockerfile

FROM node:latest AS builder

WORKDIR /app

COPY package*.json ./

RUN npm i 

COPY . .

RUN npm run build


FROM nginx:1.25-alpine

COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=builder /app/dist /usr/share/nginx/html

EXPOSE 80

CMD ["nginx", "-g", "daemon off;"]

即在前端中,需要单独配置一个 docker,并使用 nginx 部署,上述配置不详细解释了。

在后端 backend 文件夹下,也需要单独配置一个 docker:

FROM golang:1.22-alpine AS builder

ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct \
    CGO_ENABLED=0 \
    GOOS=linux \
    GOARCH=amd64

WORKDIR /build

COPY . .

RUN go mod tidy
RUN go build -o rbac .

FROM alpine:latest

WORKDIR /app

COPY ./conf /app/conf
COPY --from=builder /build/rbac .

RUN echo "https://mirrors.tuna.tsinghua.edu.cn/alpine/latest-stable/main" > /etc/apk/repositories && \
    echo "https://mirrors.tuna.tsinghua.edu.cn/alpine/latest-stable/community" >> /etc/apk/repositories
RUN apk add --no-cache busybox

目录结构如下:

|- backend
	|- Dockerfile
	|- ***
|- frontend
	|- Dockerfile
	|- nginx.conf
	|- ***
|- docker-compose.yml

这里仍然直接在一台服务器上部署,通过 docker compose 一键部署,配置如下:

version: "3.8"

services:

  mysql57:
    image: mysql:5.7
    environment:
      - "MYSQL_ROOT_PASSWORD=root"
    volumes:
      - mysqlData:/var/lib/mysql
      - ./backend/rbac.sql:/docker-entrypoint-initdb.d/rbac.sql
    networks:
      - rbac
    restart: always

  redis7:
    image: redis:7.0
    command: redis-server --requirepass redis
    restart: always
    volumes:
      - redisData:/data
    networks:
      - rbac

  rbac:
    build: ./backend
    command: sh -c "sleep 5; ./rbac"
    restart: on-failure
    ports:
      - "8080:8080"
    depends_on:
      - mysql57
      - redis7
    networks:
      - rbac

  vue:
    build: ./frontend
    ports:
      - "80:80"
    restart: always


networks:
  rbac:

volumes:
  mysqlData:
  redisData:

可以看到,vue 这个 docker 容器(实际容器名称 rbac-vue-1)不在 networkrbac 的网络中。前端界面通过 nginx 代理缓存静态资源返回,所有 rpc 通信会统一前缀 /api 并转到后端对应接口返回响应数据。这里图个方便直接全部丢在一个 docker-compose.yml 一键生成所需容器,并自动化部署。前端这个 nginx 容器独立出去也是可以的。

到此,第一个前后端项目部署就完成了,这次记录并未涉及很复杂的操作。我也使用 SSL 证书,只是自己简单购买了一个域名,写了一个前后端小项目,快速的部署了一下。文章如有错误,烦请指正。

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

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

相关文章

计算机设计大赛 深度学习交通车辆流量分析 - 目标检测与跟踪 - python opencv

文章目录 0 前言1 课题背景2 实现效果3 DeepSORT车辆跟踪3.1 Deep SORT多目标跟踪算法3.2 算法流程 4 YOLOV5算法4.1 网络架构图4.2 输入端4.3 基准网络4.4 Neck网络4.5 Head输出层 5 最后 0 前言 🔥 优质竞赛项目系列,今天要分享的是 🚩 *…

WildCard:一个因太好用而被迫暂停服务的虚拟信用卡平台,魅力何在?

如果你需要使用Wildcard开通GPT4、Midjourney或是Only方式的话,请点击:WildCard使用教程 参考文章链接:WildCard:一个因太好用而被迫暂停服务的虚拟信用卡平台,魅力何在? 1、Wildcard用户数量激增&#x…

lombok的Getter, Setter报错 cannot find symbol

今天突然发现项目里的lombok失效了,get , set全部报错 java: cannot find symbol 觉得很奇怪,年前放假前都好好的,没改过代码,依赖,注解都正确,突然报这个错。 后来才发现是因为重装过系统,id…

机器人十大前沿技术(2023-2024年)

2023-2024年机器人十大前沿技术 1. 具身智能与垂直大模型 具身智能是指拥有自主感知、交互和行动能力的智能体,能够与环境进行实时互动,从而实现对环境的理解和适应。 “大模型”是指在深度学习和人工智能领域中,使用大量参数和数据进行训…

【Visual Studio】技巧 :自动与活动文档同步

在这里插入图片描述 工具 -> 选项 -> 项目和解决方案 - 勾选上面的 我厉害不!!!

php基础学习之常用系统函数

一,有关输出的语句/函数 echo语句 用于输出一个或多个字符串 print语句 用于输出一个字符串(用句点连接的多个字符串本质是一个字符串),与echo类似,但返回值为1 printf()函数 用于格式化输出字符串,类似于C…

东方博宜 1395. 小丽找数?

东方博宜 1395. 小丽找数&#xff1f; #include<iostream> using namespace std; int main() {int x ;cin >> x ;int cnt 0 ;for (int i 1 ; i < x ; i){ int y i ;int sum 0;while(y > 0){sum y%10 ;y / 10 ;}if(sum%5!0 &&sum%2!0)cnt 1 …

莱卡云怎么样?简单测评下莱卡云韩国CN2云服务器

莱卡云服务器厂商&#xff0c;国内持证企业服务器商家&#xff0c;运作着香港、美国、韩国、镇江、日本、绍兴、枣庄、等数据中心的云服务器、独立服务器出租、设备托管、CDN等业务。今天为大家带来的是莱卡云韩国CN2服务器的详细评测&#xff0c;该云服务器的数据中心位于韩国…

网络同步—帧同步和状态同步解析

概述 同步就是要多个客户端表现效果是一致的&#xff0c;而且对于大多数的游戏&#xff0c;不仅仅要表现一致&#xff0c;还要客户端和服务器的数据也是一致的。所以同步是个网络游戏概念&#xff0c;只有网络游戏才需要同步&#xff0c;而单机游戏是不需要同步的。 帧同步和…

在vscode中使用正则表达式删除python的注释

出于一些原因&#xff0c;需要删除所有的注释 vscode中用全文搜索替换的功能 点击红色按钮即可使用正则表达式。 1. 多行注释 [|"][|"][|"](.*\n)*?.*[|"][|"][|"] 里面主要需要注意的就是不要使用贪婪匹配&#xff0c;也就是 *? 的?这里…

并查集,真好用,一次AC不是梦!

文章目录 &#x1f680;前言&#x1f680;并查集&#x1f680;并查集的两个优化✈️路径压缩✈️按秩合并 &#x1f680;并查集代码模板 &#x1f680;前言 大家好啊&#xff01;今天阿辉来给大家介绍一种简洁而优雅的数据结构——并查集&#xff0c;不知道各位是否了解它&…

Paper Digest | 突破个性化推荐数据稀疏性:长尾增强的图对比学习算法研究

00 导读 本文将介绍的论文 Long-tail Augmented Graph Contrastive Learning for Recommendation 已被 ECML/PKDD 2023 Research Track 接收。 论文链接&#xff1a;https://arxiv.org/abs/2309.11177 论文中提到的模型实现&#xff0c;已经完全复现到 OpenAGL 里了&#xff…

186205-33-4,Cyanine2活化酯,可标记各种纳米材料和生物样品

186205-33-4&#xff0c;Cyanine2 NHS Ester&#xff0c;Cy2 NHS&#xff0c;Cy2活化酯&#xff0c;Cyanine2活化酯&#xff0c;可标记各种纳米材料和生物样品 您好&#xff0c;欢迎来到新研之家 文章关键词&#xff1a;186205-33-4&#xff0c;Cyanine2 NHS Ester&#xff0…

基于 Reactive Mode 的 Flink 自动扩容

翻译自 Apache Flink: Scaling Flink automatically with Reactive Mode 简介 流式作业长时间运行过程中常常会经历不同流量负载的情况。流量负载会出现周期性的变化&#xff0c;如&#xff1a;白天与晚上、周末与工作日、节假日与非节假日&#xff0c;这些波动可能是突发事件…

消息队列(Message Queue)

目录 一、概念 二、消息队列使用场景 1.应用解耦&#xff1a;将应用进行解耦 具体场景&#xff1a;用户下单后&#xff0c;订单系统需要通知库存系统 2.异步处理&#xff1a;多应用对消息队列中同一消息进行处理&#xff0c;应用间并发处理消息&#xff0c;相比串行处理&…

当excel中表格打印预览右边超出限定页面时,调整列宽

解决办法&#xff1a;调整整体列或者部分列的列宽 操作流程如下&#xff1a; 第一步&#xff1a;选中需要调整的列 ①将鼠标放在表格的列上&#xff0c;等出现向下粗箭头后——>②单击&#xff08;变成粗十字&#xff09;该列——>③拖动选中列 第二步&#xff1a;调…

无人机技术,无人机动力系统知识,电机、电调、桨叶技术详解

无人机动力系统中的电机、电调和桨叶技术都是非常重要的部分&#xff0c;以下是对这些技术的详解&#xff1a; 无人机电机 在无人机动力系统中&#xff0c;电机是将电能转化为机械能的关键部件。其主要作用是产生旋转力矩&#xff0c;驱动螺旋桨的旋转&#xff0c;从而实现无…

【python全栈式开发】面向对象

这里写自定义目录标题 一、学习内容概述&#xff08;一&#xff09;函数式和面向对象的区别1、函数式2、面向对象 &#xff08;二&#xff09;网络编程&#xff08;三&#xff09;并发编程 二、面向对象&#xff08;一&#xff09;初识面向对象1、对象和self2、应用示例&#x…

【ARMv8M Cortex-M33 系列 8 -- RT-Thread 堆内存 检查命令 free 实现及介绍】

文章目录 RT-Thread 堆内存 检查命令 free 实现及介绍rt_memory_info 函数验证 RT-Thread 堆内存 检查命令 free 实现及介绍 在RT-Thread系统中&#xff0c;通常可以通过rt_memory_info函数获取当前的堆内存使用信息&#xff0c;然后你可以包装这个函数来显示剩余的堆空间。rt…

Python学习(16)|列表_遍历_排序_max_min_sum

列表的遍历&#xff1a; a [10,20,30,40] for obj in a: #obj 是临时变量名称&#xff0c;随意起名print(obj) 执行结果&#xff1a; 复制列表所有的元素到新列表对象&#xff1a; list1 [30,40,50] list2 list1 #只是将list2也指向了列表对象。也就是说list…
最新文章