Github Actions实现CI/CD(golang项目)

Github Actions构建CI/CD(golang项目)

1 基础概念

1.1 Actions

GitHub Actions允许构建一个完整的 CI/CD Pipeline,与 GitHub 生态系统深度集成,而无需使用 Travis CI 或者 Circle CI 等第三方服务,对于开源项目都是可以免费使用的。

1.2 workflow(什么时候做什么事情)

为了触发Github工作流,我们需要定义一个yml文件

  • workflow主要是为了定义什么时候做什么事情(on:什么时候,action:做什么事)
  • 每个 workflow 由一个或多个 Job 组成,我们的 Build Workflow 包含 3 个 Job(Lint、Build 和 Test),而 Release Workflow 只包含一个 Release 的 Job。
  • 每个 Job 都由多个 Step 组成,比如,“单元测试”的 Job 就包含获取代码、运行测试和生产代码覆盖率报告的几个步骤。
  • Workflow 会被定义在代码仓库根目录下面的.github/workflows目录中的 YAML 文件中,该目录下面的每个文件就代表了不同的工作流。

例如:Build.yml

name: Build and Test
on:
  push:
    branches:
      - master
  pull_request:

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.12

      - name: Check out code
        uses: actions/checkout@v1

      - name: Lint Go Code
        run: |
          export PATH=$PATH:$(go env GOPATH)/bin # temporary fix. See https://github.com/actions/setup-go/issues/14
          go get -u golang.org/x/lint/golint 
          make lint          

  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.12

      - name: Check out code
        uses: actions/checkout@v1

      - name: Run Unit tests.
        run: make test-coverage

      - name: Upload Coverage report to CodeCov
        uses: codecov/codecov-action@v1.0.0
        with:
          token: ${{secrets.CODECOV_TOKEN}}
          file: ./coverage.txt

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.12

      - name: Check out code
        uses: actions/checkout@v1

      - name: Build
        run: make build
1 on:触发构建条件(什么时候构建)
# 1 当推送到master或者release分支时触发构建
on:
  push:
    branches:
      - master
      - release/*

# 2 提交pr到master时构建
on:
  pull_request:
    branches:
      - master

# 3 定时任务
on:
  schedule:
    - cron: 0 2 * * 1-5

其他语法见: https://help.github.com/articles/workflow-syntax-for-github-actions

2 jobs:做什么事

yml中我们可以定义一个或多个job。

  • steps包含完成某个job具体的步骤。
  • actions 是可重复使用的工作单元,可由任何人在 GitHub 上构建和分发,我们可以在 GitHub marketplace 中找打各种各样的操作,通过指定包含 action 和 想使用的 ref 来进行操作:
# 当有push发生时,触发构建
name: CI

on: [push]
# jobs:定义一个或多个job
jobs:
  # 每个job的构建环境及steps所做操作
  build:
  	# 该job在什么环境下运行
    runs-on: ubuntu-latest
	# 该jobs需要做哪些操作
    steps:
      - uses: actions/checkout@v1
      - name: Run a one-line script
        run: echo Hello, world!
      - name: Run a multi-line script
        run: |
          echo Add other actions to build,
          echo test, and deploy your project. 

2 实战

下面我将演示通过Github Actions构建两个workflow工作流。

  1. 推送代码到 master 分支或者创建 PR 的时候将触发 Build 的 workflow
  2. 当创建了一个新的 tag 的时候,会触发 Release 的 workflow,该工作流会发布一个新的应用版本。

2.1 项目准备

  1. Github上新建[yi-github-actions]项目

在这里插入图片描述

  1. 本地init一个git仓库,并添加origin
git init
# 添加远程仓库地址
git remote add origin git@github.com:ziyifast/yi-github-actions.git
# 拉取分支
git fetch -p
git merge --ff-only
# 切换到main分支
git checkout main

2.2 Build workflow编写

这里主要讲解:main.yml的编写

Build Workflow 包含 3 个 Job(Lint、Build 和 Test)

  • Lint:检测代码格式
  • Build:构建代码
  • Test:检查测试覆盖率

项目结构:
在这里插入图片描述

1 workflow名称及触发规则:on
on:
  push:
    branches:
      - master
  pull_request:
2 workflow所包含job

整个 workflow 中包含了 3 个 Job:Lint、Test 和 Build,Lint 的 Job 定义如下:

下面我们指定了我们希望这个 Job 任务在 ubuntu 机器上运行(runs-on关键字)。Actions 现在支持 Linux、Mac、Windows 和 Docker 环境,在以后,也可以将自己的机器来作为 runners 运行,类似与 GitLab CI Runner。然后定义了该 Job 任务的执行步骤:

①LintJob
lint:
  name: Lint
  # 指定运行环境
  runs-on: ubuntu-latest
  steps:
  	# 安装Go环境,Github已经提供了对应的actions(可以理解为脚本,直接诶执行)
    - name: Set up Go
      uses: actions/setup-go@v1
      with:
        go-version: 1.19

    - name: Check out code
      uses: actions/checkout@v1
	  # 安装Go lint
    - name: Lint Go Code
      run: |
        export PATH=$PATH:$(go env GOPATH)/bin # temporary fix. See https://github.com/actions/setup-go/issues/14
        go get -u golang.org/x/lint/golint 
        make lint        
②TestJob

这里的定义唯一不同的是上传代码测试覆盖率使用的 action 是一个第三方的,当然这个 action 也在 marketplace 上面可以找到:https://github.com/marketplace/actions/codecov,我们会将测试的代码覆盖率上传到 CodeCov。这里我们需要使用 GitHub 的secrets来存储操作 CodeCov 所需要的Codecov Token,在 CodeCov 网站上通过 GitHub 用户授权登录,然后启用上面的[yi-github-actions]项目,就可以获得Codecov Token的值,然后在 GitHub 项目 settings -> Secrets 下面添加,Name 为CODECOV_TOKEN,Value 就是刚刚获取的Codecov Token的值。这样我们就完成了 Test 这个 Job 任务的操作声明。

  1. 以Github账户登录CodeCov官网
    在这里插入图片描述
  2. 点击对应项目的Configure,拷贝token信息
    在这里插入图片描述
    在这里插入图片描述
  3. 找到对应项目的settings-Secrets and variable-添加Action Secret。Name 为CODECOV_TOKEN,Value 就是刚刚获取的Codecov Token的值。
    在这里插入图片描述

拓展:

我们可以使用任何语言创建自己的 actions(只需要包含一个 Dockerfile 文件),如果你喜欢使用 Typescript 的话还可以直接使用官方提供的 action 开发工具包:https://github.com/actions/toolkit。

  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.19

      - name: Check out code
        uses: actions/checkout@v1

      - name: Run Unit tests.
        run: make test-coverage

      - name: Upload Coverage report to CodeCov
        uses: codecov/codecov-action@v1.0.0
        with:
          token: ${{secrets.CODECOV_TOKEN}}
          file: ./coverage.txt

这样我们就完成了第一个 workflow😄,不过需要注意的是我们这里所有的操作都是通过 make 命令执行的,所以我们还需要在项目根目录中添加一个 Makefile 文件,内容如下所示:

PROJECT_NAME := "github.com/ziyifast/yi-github-actions"
PKG := "$(PROJECT_NAME)"
PKG_LIST := $(shell go list ${PKG}/...)
GO_FILES := $(shell find . -name '*.go' | grep -v _test.go)

.PHONY: all dep lint vet test test-coverage build clean

all: build

dep: ## Get the dependencies
	@go mod download

lint: ## Lint Golang files
	@go install golang.org/x/lint/golint@latest
	@golint -set_exit_status ${PKG_LIST}

vet: ## Run go vet
	@go vet ${PKG_LIST}

test: ## Run unittests
	@go test -short ${PKG_LIST}

test-coverage: ## Run tests with coverage
	@go test -short -coverprofile cover.out -covermode=atomic ${PKG_LIST}
	@cat cover.out >> coverage.txt

build: dep ## Build the binary file
	@go get $(PROJECT_NAME)
	@go build -i -o build/main $(PKG)

clean: ## Remove previous build
	@rm -f ./build

help: ## Display this help screen
	@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
③Build Job
  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.19

      - name: Check out code
        uses: actions/checkout@v1

      - name: Build
        run: make build
3 main.yml

主要用于构建pr workflow工作流,当有pr提到main上时就会触发

name: Build and Test
on:
  push:
    branches:
      - main
  pull_request:

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.19

      - name: Check out code
        uses: actions/checkout@v1

      - name: Lint Go Code
        run: |
          go install golang.org/x/lint/golint@latest
          export PATH="$PATH:$HOME/go/bin"
          make lint
    

  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.19

      - name: Check out code
        uses: actions/checkout@v1

      - name: Run Unit tests.
        run: make test-coverage

      - name: Upload Coverage report to CodeCov
        uses: codecov/codecov-action@v1.0.0
        with:
          token: ${{secrets.CODECOV_TOKEN}}
          file: ./coverage.txt

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.19

      - name: Check out code
        uses: actions/checkout@v1

      - name: Build
        run: make build

2.3 Release workflow编写

有了上面的基础,编写第二个工作流就很简单了。我们要实现给代码打上tag时,就触发release,发布一个release包。

release.yml:

name: Release
on:
  create:
    tags:
      - v*

jobs:
  release:
    name: Release on GitHub
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v1

      - name: Validates GO releaser config
        uses: docker://goreleaser/goreleaser:latest
        with:
          args: check

      - name: Create release on GitHub
        uses: docker://goreleaser/goreleaser:latest
        with:
          args: release
        env:
          #GITHUB_TOKEN,Github已经帮我们建好了,我们直接使用即可
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}

3 全部代码及验证

全部代码:https://github.com/ziyifast/yi-github-actions/actions

3.1 代码

项目结构:
在这里插入图片描述

1 yi-github-actions/service/user_service.go
package service

type userService struct {
}

// UserService get user name
var UserService = new(userService)

func (u *userService) GetUserName() string {
	return "tom"
}
2 yi-github-actions/service/user_service_test.go
package service

import "testing"

func Test_userService_GetUserName(t *testing.T) {
	tests := []struct {
		name string
		want string
	}{
		{"test", "tom"},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			u := &userService{}
			if got := u.GetUserName(); got != tt.want {
				t.Errorf("GetUserName() = %v, want %v", got, tt.want)
			}
		})
	}
}
3 yi-github-actions/main.go
package main

import (
	"fmt"
	service "github.com/ziyifast/yi-github-actions/service"
)

func main() {
	fmt.Println("before...")
	fmt.Println("got a user: ", service.UserService.GetUserName())
}
4 yi-github-actions/Makefile
PROJECT_NAME := "github.com/ziyifast/yi-github-actions"
PKG := "$(PROJECT_NAME)"
PKG_LIST := $(shell go list ${PKG}/...)
GO_FILES := $(shell find . -name '*.go' | grep -v _test.go)

.PHONY: all dep lint vet test test-coverage build clean

all: build

dep: ## Get the dependencies
	@go mod download

lint: ## Lint Golang files
	@go install golang.org/x/lint/golint@latest
	@golint -set_exit_status ${PKG_LIST}

vet: ## Run go vet
	@go vet ${PKG_LIST}

test: ## Run unittests
	@go test -short ${PKG_LIST}

test-coverage: ## Run tests with coverage
	@go test -short -coverprofile cover.out -covermode=atomic ${PKG_LIST}
	@cat cover.out >> coverage.txt

build: dep ## Build the binary file
	@go get $(PROJECT_NAME)
	@go build -i -o build/main $(PKG)

clean: ## Remove previous build
	@rm -f ./build

help: ## Display this help screen
	@grep -h -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
5 yi-github-actions/.github/workflows/main.yml
name: Build and Test
on:
  push:
    branches:
      - main
  pull_request:

jobs:
  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.19

      - name: Check out code
        uses: actions/checkout@v1

      - name: Lint Go Code
        run: |
          go install golang.org/x/lint/golint@latest
          export PATH="$PATH:$HOME/go/bin"
          make lint
    

  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.19

      - name: Check out code
        uses: actions/checkout@v1

      - name: Run Unit tests.
        run: make test-coverage

      - name: Upload Coverage report to CodeCov
        uses: codecov/codecov-action@v1.0.0
        with:
          token: ${{secrets.CODECOV_TOKEN}}
          file: ./coverage.txt

  build:
    name: Build
    runs-on: ubuntu-latest
    needs: [lint, test]
    steps:
      - name: Set up Go
        uses: actions/setup-go@v1
        with:
          go-version: 1.19

      - name: Check out code
        uses: actions/checkout@v1

      - name: Build
        run: make build
6 yi-github-actions/.github/workflows/release.yml
name: Release
on:
  create:
    tags:
      - v*

jobs:
  release:
    name: Release on GitHub
    runs-on: ubuntu-latest
    steps:
      - name: Check out code
        uses: actions/checkout@v1

      - name: Validates GO releaser config
        uses: docker://goreleaser/goreleaser:latest
        with:
          args: check

      - name: Create release on GitHub
        uses: docker://goreleaser/goreleaser:latest
        with:
          args: release
        env:
          GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
7 yi-github-actions/go.mod
module github.com/ziyifast/yi-github-actions

go 1.19

3.2 验证

①pr workflow(main.yml)

触发条件,向main分支提交pr

# 本地新建一个分支,随便修改点文件,然后给远程提交pr
git checkout -b ziyi origin/main
git push origin ziyi

来到Github上提交一个pr,触发构建:
在这里插入图片描述
在这里插入图片描述

完成之后,可以到cover上查看测试覆盖率:

②release workflow(release.yml)

本地打一个tag,然后推送到远程

# 本地打上v1.0.3这个tag
git tag v1.0.3
# 将tag推送到远程
git push origin v1.0.3 

在这里插入图片描述
成功触发构建:
在这里插入图片描述
同时也生成了对应的assets文件:
在这里插入图片描述
点击cover链接,也可以查看单元覆盖率:

Tips:

  1. 点击Actions可以查看构建记录,以及错误原因:
    在这里插入图片描述
  2. Github Actions可以结合仓库rules使用,比如:如果lint没通过,就不让merge代码
    在这里插入图片描述
bug:构建报403

如果触发之后报403,则表示权限不足。

在这里插入图片描述

仓库-Settings-Actions-General-Actions permissions-Workflow permissions,勾选上Read and Write Permission

在这里插入图片描述

4 拓展:actions配合pr check

为了保证我们代码的规范和合法,在提交代码到main之前,我们需要让pr通过一定的检测,比如:lint、test、build等。

  1. 创建Rule set
  • 仓库 - Settings - Rule - New branch rule set。新建一个branch规则
    在这里插入图片描述
  1. 配置规则
  • Bypass List:配置xxx可以绕过该规则
  • Target branches:配置对哪个分支生效在这里插入图片描述
  • Require status checks to pass:需要workflow检查通过才能合入
    这里的Test与Lint为workflow.yml中的Job名称在这里插入图片描述
  1. 点击create,输入密码进行校验
    在这里插入图片描述
  2. 可以看到创建成功,并且规则是启用状态
    在这里插入图片描述
  3. 修改代码并提交,观察校验通过后是否能正常合入

可以看到检测通过后,普通用户可正常合入

在这里插入图片描述

  1. 修改user_service_test.go,让其单元检测不过
  • 可以看到检验不通过,无法merge代码
    在这里插入图片描述
  1. 修改规则,将当前用户加入ByPassList,重新提交pr,发现可以绕过规则,强行合入
    在这里插入图片描述

原文地址:https://dev.to/brpaz/building-a-basic-ci-cd-pipeline-for-a-golang-application-using-github-actions-icj

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

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

相关文章

在IDEA中解决SSM项目修改图片不能回显问题

1.问题描述 图片成功上传之后,件夹中已经显示图片了,但是访问图片资源会出现404错误,再重新启动服务器之后,发现这个错误又消失了,图片又能正常显示,但是必须重启Tomcat才有效。 2.解决方法如下&#xff…

一键生成数据库文档,从此告别人工整理文档

背景 在我们日常开发过程中,常常遇到项目需要出一个数据库文档,面对数据表众多的场景一个一个写显然不现实,于是 screw工具很好的满足了我们的需求,从此告别人工整理文档; screw工具它可以将整个数据库的表输出为数据库表结构文档…

【Linux】服务器时区 [ CST | UTC | GMT | RTC ]

目录 1. 硬件时间(Real_TIME Clock [RTC time]) 1.1 硬件时间简介 1.2 如何使用硬件时间 2. 系统时间(UTC时间)(Universal time) 2.1 系统时间简介 2.2 UTC时间 3. 本地时间(Local time&…

淘宝/天猫获取sku详细信息 API,item_sku-获取sku详细信息

淘宝/天猫获取sku详细信息 API,item_sku-获取sku详细信息 示例: {"seller_rate": true,"timeout_action_time": "2000-01-01 00:00:00","iid": "152e442aefe88dd41cb0879232c0dcb0","num": 10,"…

【UKE!】2024.4.19

2024.4.19 【你知道的都是真相。只可惜那些并不是真相的全部。】 Friday 三月十一 谷雨 <BGM “谷雨–音阙诗听”> AC :Answer Coarse,粗劣的答案 ​ CE :Compile Easily,轻松通过 ​ PC :Perfect Compile 完美的编译 ​ WA :Wonderful Answer,好答案 ​ RE :Run Exce…

C++设计模式:代理模式(十三)

1、代理模式 定义&#xff1a;为其他对象提供一种代理以控制&#xff08;隔离使用接口&#xff09;对这个对象的访问等。 动机 在面向对象系统中&#xff0c;有些对象由于某种原因&#xff08;比如对象需要进程外的访问等&#xff0c;例如在分布式的系统中&#xff09;&#x…

基于springboot实现工程教育认证的计算机课程管理平台项目【项目源码+论文说明】

基于springboot实现计算机课程管理平台系统演示 摘要 随着信息技术在管理上越来越深入而广泛的应用&#xff0c;管理信息系统的实施在技术上已逐步成熟。本文介绍了基于工程教育认证的计算机课程管理平台的开发全过程。通过分析基于工程教育认证的计算机课程管理平台管理的不足…

Liunx挂载硬件设备

一、mount命令&#xff08;用于挂载文件系统&#xff09; &#xff08;一&#xff09;语法格式&#xff1a;mount 参数 源设备路径 目的路径 &#xff08;二&#xff09;参数 1、-t&#xff1a;指定挂载的文件系统 &#xff08;1&#xff09;iso9660&#xff1a;光盘或光盘…

uniapp H5项目 获取接口的二进制流转化成图片url(base64)

如果你使用的是uniapp, 并且你从接口获取下来的数据长这样&#xff1a; 想要把取到的数据展示成图片&#xff0c;那么你可以这样做&#xff1a; // 这是我们的项目封装的请求方法const res await this.$api.getKaptcha({originResponse: true, // 这样写是为了在request那边特…

输电线路运行特性及简单电力系统潮流估算(三)

本篇为本科课程《电力系统稳态分析》的笔记。 本篇为这一章的第三篇笔记。上一篇传送门。 辐射型网络和简单闭式网络的潮流估算方法 辐射型网络的潮流估算方法 指的是在网络中不含环形电路&#xff0c;为开式网络&#xff0c;而且全部负荷都只能用一个电源来供电的网络。 …

logistic分叉图

MATLAB代码 % 初始化 r_min 2.5; % 参数r的起始值 r_max 4.0; % 参数r的结束值 r_step 0.001; % 参数r的步长 r_values r_min:r_step:r_max; % 参数r的范围% 分岔图数据初始化 num_iterations 1000; % 总迭代次数 num_last_points 100; % 用于绘图的最后的这些…

idea2024.1发布,lambda多语句的内联断点,增强spring图标等新特性,你没玩过的全新版本

这里是weihubeats,觉得文章不错可以关注公众号小奏技术 简述 2024-04-04 idea官方宣布发布了 一些重大更新 随后我便下载了你没玩过的全新版本IntelliJ IDEA Ultimeate版本试玩 然后脑子里面想到这个 开玩笑 实际下载完是这样 更新内容 更新的内容比较多 关键亮点主要有如下…

VUE 使用 Vite 创建一个 vue3.0 + vite 项目

Vite 是一种新型前端构建工具&#xff0c;能够显著提升前端开发体验。它主要由两部分组成&#xff1a; 1. 一个开发服务器&#xff0c;它基于 原生 ES 模块 提供了 丰富的内建功能&#xff0c;如速度快到惊人的 模块热更新&#xff08;HMR&#xff09;。 2. 一套构建指令&#…

每日算法练习(1)

开一个新坑&#xff0c;记录下自己每天的算法练习&#xff0c;希望自己通过1个多月的学习&#xff0c;能够成为算法大神。 下面正式开始新坑。 两个数组的交集 这是牛客上的题&#xff0c;根据题意&#xff0c;我们有多种解法&#xff0c;这题用哈希比较好写。我们可以弄一个…

智慧公厕解决方案易集成好使用的智能硬件

在现代城市建设中&#xff0c;智慧公厕的需求日益增长。为了提供更好的用户体验和更高效的管理&#xff0c;易集成、好使用的智能硬件成为智慧公厕解决方案的关键组成部分。 1. 蹲位有人无人感应器&#xff1a;是用于检测厕位有人无人的设备&#xff0c;根据现场不同的安装条件…

【管理咨询宝藏78】MBB大型城投集团核心能力建设分析报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏78】MBB大型城投集团核心能力建设分析报告 【格式】PDF版本 【关键词】战略规划、商业分析、管理咨询、MBB顶级咨询公司 【强烈推荐】 这是一套…

Java中的栈和队列

1.前言 在计算机科学中&#xff0c;数据结构是用来组织和存储数据的方式&#xff0c;以便可以高效地访问和修改。栈和队列是两种最基本的数据结构&#xff0c;它们在各种计算过程中都有广泛的应用。本文将介绍栈和队列的概念、特性以及它们的一些常见应用。 2.栈 2.1概念 栈…

Vue实现多角色登录,Vue-Router路由守卫控制权限页面

实现页面侧边栏和头部不变&#xff0c;当点击某个功能时&#xff0c;只有主体部分发生变化&#xff0c;这要用到子路由技术 我的项目结构如上&#xff0c;其中包含侧边栏和头部的文件是Manage.vue&#xff0c;主页面是Home.vue&#xff0c;个人页面是Person.vue&#xff0c;用户…

kaggle咖啡销售分析案例侧重可视化折线图条形图扇形图柱状图

目录 概述 环境依赖 数据描述 代码概述 导包 数据读取 统计缺失值 数据结构概述 描述统计 时间轴数据转换 月交易统计直方图 周交易统计图 小时数据转换 小时折线图 销售关系可视化统计 销售占比扇形图 价格箱线图 各类别多维度条形图统计 商店位置交易量折线…

9个技巧使你的Python代码更Pythonic!

如何区分漂亮和丑陋的代码&#xff1f; 更重要的是&#xff0c;如何写出漂亮的 Python 代码&#xff1f; 本文将通过初学者容易理解的例子展示9个神话般的Python技巧&#xff0c;以帮助你在日常工作中编写更多的Pythonic程序。 01 product() 使用 product() 函数避免嵌套的…