Tuesday, April 13, 2021

V2EX - 技术

V2EX - 技术


关于 Notion 插入代码的问题,以及其他同类笔记软件推荐?

Posted: 13 Apr 2021 04:20 AM PDT

日经问题:笔记软件的选择。。。

用了好多年 OneNote,不过碍于以下几个问题现在想弃坑了:

  1. 字体问题,下英文字体动不动变成 calibri,很不爽。(用了 OneFont 基本解决问题)
  2. 对插入代码的支持很差,不支持高亮,而且有时复制出来时会有奇怪的字符,导致粘贴后不能直接运行。
  3. 如果在页面中创建了多个框,则不能自适应宽度,然后移动端上就要拖来拖去才能看。
  4. 无本地文件( UWP 和 Mac 版)。

然后最近试用了一周 Notion,总体感觉还不错,目前遇到两个问题比较影响体验(也可能是我不会用,求指点):

  1. 代码块问题。难以跳出代码块,比如代码块是页面的最后一个 block 时,没有办法快速地在代码块下方新增一行,必须用鼠标点加号才能达到。另外,似乎不支持用"```cpp"这种方式指定语言,打完三个反引号后就直接变成代码块了,必须手动在指定语言。
  2. 行内代码问题。用单个反引号创建行内代码感觉不太好用,反引号前面必须有空格才行。我的习惯和中文文案排版指北基本一样,全角标点与英文之间不加空格,所以如果想在中文句号后面紧跟行内代码的话就很麻烦。如果用 Ctrl+E,又会产生另一个问题,就是难以跳出:当光标在行内代码的最后一个字符和它后面紧跟的字符的中间位置时,无法确定光标到底是在行内代码的内部还是外部。

如果这些问题在 Notion 上没有解决办法,求推荐其他软件。我的需求大概是下面这样的:

  1. 支持 Markdown 的全部或绝大部分语法
  2. 支持代码高亮,且插入和编辑代码(包括代码块和行内代码)的体验要好,不要有上面 Notion 的问题
  3. 有离线文件,或支持导出(导出 Markdown 最佳,HTLM 、PDF 也行)
  4. 支持多设备同步( Win/Mac/iOS ),Web 也行。可以接受自建服务器
  5. 国外软件更佳,最好不要太小众(免得跑路)

我的笔记一般比较简单,主要是线性的文字、图片、代码块,不需要太过自由的排版功能(如 OneNote ),像 Notion 那样支持以固定规则拖动的排版方式就很好,也不太需要复杂的数据库、表格功能。

谢谢大家!

堡垒机是为了监控管理员行为,那谁来监控运维堡垒机的管理员

Posted: 13 Apr 2021 04:17 AM PDT

MixGo v1.1 发布, Go 快速开发脚手架工具

Posted: 13 Apr 2021 04:07 AM PDT

Mix Go 是一个基于 Go 进行快速开发的完整系统,类似前端的 Vue CLI,提供:

  • 通过 mix-go/mixcli 实现的交互式项目脚手架:
    • 可以生成 cli, api, web, grpc 多种项目代码
    • 生成的代码开箱即用
    • 可选择是否需要 .env 环境配置
    • 可选择是否需要 .yml, .json, .toml 等独立配置
    • 可选择使用 gorm, xorm 的数据库
    • 可选择使用 logrus, zap 的日志库
  • 通过 mix-go/xcli 实现的命令行原型开发。
  • 基于 mix-go/xdi 的 DI, IoC 容器。

Github | Gitee

快速开始

安装

go get github.com/mix-go/mixcli 

创建项目

$ mixcli new hello Use the arrow keys to navigate: ↓ ↑ → ←  ? Select project type:   ▸ CLI     API     Web (contains the websocket)     gRPC 

技术交流

知乎: https://www.zhihu.com/people/onanying
微博: http://weibo.com/onanying
官方 QQ 群:284806582, 825122875,敲门暗号:goer

编写一个 CLI 程序

首先我们使用 mixcli 命令创建一个项目骨架:

$ mixcli new hello Use the arrow keys to navigate: ↓ ↑ → ←  ? Select project type:   ▸ CLI     API     Web (contains the websocket)     gRPC 

生成骨架目录结构如下:

. ├── README.md ├── bin ├── commands ├── conf ├── configor ├── di ├── dotenv ├── go.mod ├── go.sum ├── logs └── main.go 

mian.go 文件:

  • xcli.AddCommand 方法传入的 commands.Commands 定义了全部的命令
package main  import (   "github.com/mix-go/cli-skeleton/commands"   _ "github.com/mix-go/cli-skeleton/configor"   _ "github.com/mix-go/cli-skeleton/di"   _ "github.com/mix-go/cli-skeleton/dotenv"   "github.com/mix-go/dotenv"   "github.com/mix-go/xcli" )  func main() {   xcli.SetName("app").     SetVersion("0.0.0-alpha").     SetDebug(dotenv.Getenv("APP_DEBUG").Bool(false))   xcli.AddCommand(commands.Commands...).Run() } 

commands/main.go 文件:

我们可以在这里自定义命令,查看更多

  • RunI 定义了 hello 命令执行的接口,也可以使用 Run 设定一个匿名函数
package commands  import (   "github.com/mix-go/xcli" )  var Commands = []*xcli.Command{   {     Name:  "hello",     Short: "\tEcho demo",     Options: []*xcli.Option{       {         Names: []string{"n", "name"},         Usage: "Your name",       },       {         Names: []string{"say"},         Usage: "\tSay ...",       },     },     RunI: &HelloCommand{},   }, } 

commands/hello.go 文件:

业务代码写在 HelloCommand 结构体的 main 方法中

  • 代码中可以使用 flag 获取命令行参数,查看更多
package commands  import (   "fmt"   "github.com/mix-go/xcli/flag" )  type HelloCommand struct { }  func (t *HelloCommand) Main() {   name := flag.Match("n", "name").String("OpenMix")   say := flag.Match("say").String("Hello, World!")   fmt.Printf("%s: %s\n", name, say) } 

接下来我们编译上面的程序:

  • linux & macOS
go build -o bin/go_build_main_go main.go 
  • win
go build -o bin/go_build_main_go.exe main.go 

查看全部命令的帮助信息:

$ cd bin $ ./go_build_main_go  Usage: ./go_build_main_go [OPTIONS] COMMAND [opt...]  Global Options:   -h, --help    Print usage   -v, --version Print version information  Commands:   hello         Echo demo  Run './go_build_main_go COMMAND --help' for more information on a command.  Developed with Mix Go framework. (openmix.org/mix-go) 

查看上面编写的 hello 命令的帮助信息:

$ ./go_build_main_go hello --help Usage: ./go_build_main_go hello [opt...]  Command Options:   -n, --name    Your name   --say         Say ...  Developed with Mix Go framework. (openmix.org/mix-go) 

执行 hello 命令,并传入两个参数:

$ ./go_build_main_go hello --name=liujian --say=hello liujian: hello 

编写一个 Worker Pool 队列消费

队列消费是高并发系统中最常用的异步处理模型,通常我们是编写一个 CLI 命令行程序在后台执行 Redis 、RabbitMQ 等 MQ 的队列消费,并将处理结果落地到 mysql 等数据库中,由于这类需求的标准化比较容易,因此我们开发了 mix-go/xwp 库来处理这类需求,基本上大部分异步处理类需求都可使用。

新建 commands/workerpool.go 文件:

  • workerpool.NewDispatcher(jobQueue, 15, NewWorker) 创建了一个调度器
  • NewWorker 负责初始化执行任务的工作协程
  • 任务数据会在 worker.Do 方法中触发,我们只需要将我们的业务逻辑写到该方法中即可
  • 当程序接收到进程退出信号时,调度器能平滑控制所有的 Worker 在执行完队列里全部的任务后再退出调度,保证数据的完整性
package commands  import (     "context"     "fmt"     "github.com/mix-go/cli-skeleton/di"     "github.com/mix-go/xwp"     "os"     "os/signal"     "strings"     "syscall"     "time" )  type worker struct {     xwp.WorkerTrait }  func (t *worker) Do(data interface{}) {     defer func() {         if err := recover(); err != nil {             logger := di.Logrus()             logger.Error(err)         }     }()      // 执行业务处理     // ...          // 将处理结果落地到数据库     // ... }  func NewWorker() xwp.Worker {     return &worker{} }  type WorkerPoolDaemonCommand struct { }  func (t *WorkerPoolDaemonCommand) Main() {     redis := globals.Redis()     jobQueue := make(chan interface{}, 50)     d := xwp.NewDispatcher(jobQueue, 15, NewWorker)      ch := make(chan os.Signal)     signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)     go func() {         <-ch         d.Stop()     }()      go func() {         for {             res, err := redis.BRPop(context.Background(), 3*time.Second, "foo").Result()             if err != nil {                 if strings.Contains(err.Error(), "redis: nil") {                     continue                 }                 fmt.Println(fmt.Sprintf("Redis Error: %s", err))                 d.Stop();                 return             }             // brPop 命令最后一个键才是值             jobQueue <- res[1]         }     }()      d.Run() // 阻塞代码,直到任务全部执行完成并且全部 Worker 停止 } 

接下来只需要把这个命令通过 xcli.AddCommand 注册到 CLI 中即可。

编写一个 API 服务

首先我们使用 mixcli 命令创建一个项目骨架:

$ mixcli new hello Use the arrow keys to navigate: ↓ ↑ → ←  ? Select project type:     CLI   ▸ API     Web (contains the websocket)     gRPC 

生成骨架目录结构如下:

. ├── README.md ├── bin ├── commands ├── conf ├── configor ├── controllers ├── di ├── dotenv ├── go.mod ├── go.sum ├── main.go ├── middleware ├── routes └── runtime 

mian.go 文件:

  • xcli.AddCommand 方法传入的 commands.Commands 定义了全部的命令
package main  import (   "github.com/mix-go/api-skeleton/commands"   _ "github.com/mix-go/api-skeleton/configor"   _ "github.com/mix-go/api-skeleton/di"   _ "github.com/mix-go/api-skeleton/dotenv"   "github.com/mix-go/dotenv"   "github.com/mix-go/xcli" )  func main() {   xcli.SetName("app").     SetVersion("0.0.0-alpha").     SetDebug(dotenv.Getenv("APP_DEBUG").Bool(false))   xcli.AddCommand(commands.Commands...).Run() } 

commands/main.go 文件:

我们可以在这里自定义命令,查看更多

  • RunI 指定了命令执行的接口,也可以使用 Run 设定一个匿名函数
package commands  import (   "github.com/mix-go/xcli" )  var Commands = []*xcli.Command{   {     Name:  "api",     Short: "\tStart the api server",     Options: []*xcli.Option{       {         Names: []string{"a", "addr"},         Usage: "\tListen to the specified address",       },       {         Names: []string{"d", "daemon"},         Usage: "\tRun in the background",       },     },     RunI: &APICommand{},   }, } 

commands/api.go 文件:

业务代码写在 APICommand 结构体的 main 方法中,生成的代码中已经包含了:

  • 监听信号停止服务
  • 根据模式打印日志
  • 可选的后台守护执行

基本上无需修改即可上线使用

package commands  import (   "context"   "fmt"   "github.com/gin-gonic/gin"   "github.com/mix-go/api-skeleton/di"   "github.com/mix-go/api-skeleton/routes"   "github.com/mix-go/dotenv"   "github.com/mix-go/xcli/flag"   "github.com/mix-go/xcli/process"   "os"   "os/signal"   "strings"   "syscall"   "time" )  type APICommand struct { }  func (t *APICommand) Main() {   if flag.Match("d", "daemon").Bool() {     process.Daemon()   }    logger := di.Logrus()   server := di.Server()   addr := dotenv.Getenv("GIN_ADDR").String(":8080")   mode := dotenv.Getenv("GIN_MODE").String(gin.ReleaseMode)    // server   gin.SetMode(mode)   router := gin.New()   routes.SetRoutes(router)   server.Addr = flag.Match("a", "addr").String(addr)   server.Handler = router    // signal   ch := make(chan os.Signal)   signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)   go func() {     <-ch     logger.Info("Server shutdown")     ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)     if err := server.Shutdown(ctx); err != nil {       logger.Errorf("Server shutdown error: %s", err)     }   }()    // logger   if mode != gin.ReleaseMode {     handlerFunc := gin.LoggerWithConfig(gin.LoggerConfig{       Formatter: func(params gin.LogFormatterParams) string {         return fmt.Sprintf("%s|%s|%d|%s",           params.Method,           params.Path,           params.StatusCode,           params.ClientIP,         )       },       Output: logger.Out,     })     router.Use(handlerFunc)   }    // run   welcome()   logger.Infof("Server start at %s", server.Addr)   if err := server.ListenAndServe(); err != nil && !strings.Contains(err.Error(), "http: Server closed") {     panic(err)   } } 

routes/main.go 文件中配置路由:

已经包含一些常用实例,只需要在这里新增路由即可开始开发

package routes  import (   "github.com/gin-gonic/gin"   "github.com/mix-go/api-skeleton/controllers"   "github.com/mix-go/api-skeleton/middleware" )  func SetRoutes(router *gin.Engine) {   router.Use(gin.Recovery()) // error handle    router.GET("hello",     middleware.CorsMiddleware(),     func(ctx *gin.Context) {       hello := controllers.HelloController{}       hello.Index(ctx)     },   )    router.POST("users/add",     middleware.AuthMiddleware(),     func(ctx *gin.Context) {       hello := controllers.UserController{}       hello.Add(ctx)     },   )    router.POST("auth", func(ctx *gin.Context) {     auth := controllers.AuthController{}     auth.Index(ctx)   }) } 

接下来我们编译上面的程序:

  • linux & macOS
go build -o bin/go_build_main_go main.go 
  • win
go build -o bin/go_build_main_go.exe main.go 

启动服务器

$ bin/go_build_main_go api              ___           ______ ___  _ /__ ___ _____ ______    / __ `__ \/ /\ \/ /__  __ `/  __ \  / / / / / / / /\ \/ _  /_/ // /_/ / /_/ /_/ /_/_/ /_/\_\  \__, / \____/                       /____/   Server      Name:      mix-api Listen      Addr:      :8080 System      Name:      darwin Go          Version:   1.13.4 Framework   Version:   1.0.9 time=2020-09-16 20:24:41.515 level=info msg=Server start file=api.go:58 

编写一个 Web 服务

内容放不下,省略...

编写一个 gRPC 服务、客户端

首先我们使用 mixcli 命令创建一个项目骨架:

$ mixcli new hello Use the arrow keys to navigate: ↓ ↑ → ←  ? Select project type:     CLI     API     Web (contains the websocket)   ▸ gRPC 

生成骨架目录结构如下:

. ├── README.md ├── bin ├── commands ├── conf ├── configor ├── di ├── dotenv ├── go.mod ├── go.sum ├── main.go ├── protos ├── runtime └── services 

mian.go 文件:

  • xcli.AddCommand 方法传入的 commands.Commands 定义了全部的命令
package main  import (   "github.com/mix-go/dotenv"   "github.com/mix-go/grpc-skeleton/commands"   _ "github.com/mix-go/grpc-skeleton/configor"   _ "github.com/mix-go/grpc-skeleton/di"   _ "github.com/mix-go/grpc-skeleton/dotenv"   "github.com/mix-go/xcli" )  func main() {   xcli.SetName("app").     SetVersion("0.0.0-alpha").     SetDebug(dotenv.Getenv("APP_DEBUG").Bool(false))   xcli.AddCommand(commands.Commands...).Run() } 

commands/main.go 文件:

我们可以在这里自定义命令,查看更多

  • 定义了 grpc:servergrpc:client 两个子命令
  • RunI 指定了命令执行的接口,也可以使用 Run 设定一个匿名函数
package commands  import (   "github.com/mix-go/xcli" )  var Commands = []*xcli.Command{   {     Name:  "grpc:server",     Short: "gRPC server demo",     Options: []*xcli.Option{       {         Names: []string{"d", "daemon"},         Usage: "Run in the background",       },     },     RunI: &GrpcServerCommand{},   },   {     Name:  "grpc:client",     Short: "gRPC client demo",     RunI:  &GrpcClientCommand{},   }, } 

protos/user.proto 数据结构文件:

客户端与服务器端代码中都需要使用 .proto 生成的 go 代码,因为双方需要使用该数据结构通讯

  • .protogRPC 通信的数据结构文件,采用 protobuf 协议
syntax = "proto3";  package go.micro.grpc.user; option go_package = ".;protos";  service User {     rpc Add(AddRequest) returns (AddResponse) {} }  message AddRequest {     string Name = 1; }  message AddResponse {     int32 error_code = 1;     string error_message = 2;     int64 user_id = 3; } 

然后我们需要安装 gRPC 相关的编译程序:

接下来我们开始编译 .proto 文件:

  • 编译成功后会在当前目录生成 protos/user.pb.go 文件
cd protos protoc --go_out=plugins=grpc:. user.proto 

commands/server.go 文件:

服务端代码写在 GrpcServerCommand 结构体的 main 方法中,生成的代码中已经包含了:

  • 监听信号停止服务
  • 可选的后台守护执行
  • pb.RegisterUserServer 注册了一个默认服务,用户只需要扩展自己的服务即可
package commands  import (   "github.com/mix-go/dotenv"   "github.com/mix-go/grpc-skeleton/di"   pb "github.com/mix-go/grpc-skeleton/protos"   "github.com/mix-go/grpc-skeleton/services"   "github.com/mix-go/xcli/flag"   "github.com/mix-go/xcli/process"   "google.golang.org/grpc"   "net"   "os"   "os/signal"   "strings"   "syscall" )  var listener net.Listener  type GrpcServerCommand struct { }  func (t *GrpcServerCommand) Main() {   if flag.Match("d", "daemon").Bool() {     process.Daemon()   }    addr := dotenv.Getenv("GIN_ADDR").String(":8080")   logger := di.Logrus()    // listen   listener, err := net.Listen("tcp", addr)   if err != nil {     panic(err)   }   listener = listener    // signal   ch := make(chan os.Signal)   signal.Notify(ch, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM)   go func() {     <-ch     logger.Info("Server shutdown")     if err := listener.Close(); err != nil {       panic(err)     }   }()    // server   s := grpc.NewServer()   pb.RegisterUserServer(s, &services.UserService{})    // run   welcome()   logger.Infof("Server run %s", addr)   if err := s.Serve(listener); err != nil && !strings.Contains(err.Error(), "use of closed network connection") {     panic(err)   } } 

services/user.go 文件:

服务端代码中注册的 services.UserService{} 服务代码如下:

只需要填充业务逻辑即可

package services  import (   "context"   pb "github.com/mix-go/grpc-skeleton/protos" )  type UserService struct { }  func (t *UserService) Add(ctx context.Context, in *pb.AddRequest) (*pb.AddResponse, error) {   // 执行数据库操作   // ...    resp := pb.AddResponse{     ErrorCode:    0,     ErrorMessage: "",     UserId:       10001,   }   return &resp, nil } 

commands/client.go 文件:

客户端代码写在 GrpcClientCommand 结构体的 main 方法中,生成的代码中已经包含了:

  • 通过环境配置获取服务端连接地址
  • 设定了 5s 的执行超时时间
package commands  import (     "context"     "fmt"   "github.com/mix-go/dotenv"   pb "github.com/mix-go/grpc-skeleton/protos"     "google.golang.org/grpc"     "time" )  type GrpcClientCommand struct { }  func (t *GrpcClientCommand) Main() {   addr := dotenv.Getenv("GIN_ADDR").String(":8080")     ctx, _ := context.WithTimeout(context.Background(), time.Duration(5)*time.Second)     conn, err := grpc.DialContext(ctx, addr, grpc.WithInsecure(), grpc.WithBlock())     if err != nil {         panic(err)     }     defer func() {         _ = conn.Close()     }()     cli := pb.NewUserClient(conn)     req := pb.AddRequest{         Name: "xiaoliu",     }     resp, err := cli.Add(ctx, &req)     if err != nil {         panic(err)     }     fmt.Println(fmt.Sprintf("Add User: %d", resp.UserId)) } 

接下来我们编译上面的程序:

  • linux & macOS
go build -o bin/go_build_main_go main.go 
  • win
go build -o bin/go_build_main_go.exe main.go 

首先在命令行启动 grpc:server 服务器:

$ bin/go_build_main_go grpc:server              ___           ______ ___  _ /__ ___ _____ ______    / __ `__ \/ /\ \/ /__  __ `/  __ \  / / / / / / / /\ \/ _  /_/ // /_/ / /_/ /_/ /_/_/ /_/\_\  \__, / \____/                       /____/   Server      Name:      mix-grpc Listen      Addr:      :8080 System      Name:      darwin Go          Version:   1.13.4 Framework   Version:   1.0.20 time=2020-11-09 15:08:17.544 level=info msg=Server run :8080 file=server.go:46 

然后开启一个新的终端,执行下面的客户端命令与上面的服务器通信

$ bin/go_build_main_go grpc:client Add User: 10001 

如何使用 DI 容器中的 Logger 、Database 、Redis 等组件

项目中要使用的公共组件,都定义在 di 目录,框架默认生成了一些常用的组件,用户也可以定义自己的组件,查看更多

  • 可以在哪里使用

可以在代码的任意位置使用,但是为了可以使用到环境变量和自定义配置,通常我们在 xcli.Command 结构体定义的 RunRunI 中使用。

  • 使用日志,比如:logruszap
logger := di.Logrus() logger.Info("test") 
  • 使用数据库,比如:gormxorm
db := di.Gorm() user := User{Name: "Jinzhu", Age: 18, Birthday: time.Now()} result := db.Create(&user) fmt.Println(result) 
  • 使用 Redis,比如:go-redis
rdb := di.GoRedis() val, err := rdb.Get(context.Background(), "key").Result() if err != nil {     panic(err) } fmt.Println("key", val) 

依赖

官方库

第三方库

License

Apache License Version 2.0, http://www.apache.org/licenses/

求解一个 VB 代码修改文件名的问题

Posted: 13 Apr 2021 03:39 AM PDT

代码:

My.Computer.FileSystem.RenameFile("C:\Windows\INF\usbstor.inf", "usbstop.inf") 

本意为修改 C:\Windows\INF\usbstor.inf 的文件名,提示错误"对路径的访问被拒绝"

理解为权限问题,但是程序权限修改为 requireAdministrator或者highestAvailable都不行,google 没解决

ps: 手动修改该文件名系统也会提示你需要trustedinstaller提供的权限才能对此文件进行更改,无法修改

做小游戏上到应用商店(非国内)能赚到钱吗?

Posted: 13 Apr 2021 03:24 AM PDT

类似 Flappy Bird 这种比较简单的 2D 小游戏

业余时间写了个安卓天气 App,欢迎大家试用提提意见

Posted: 13 Apr 2021 03:06 AM PDT

酷安: https://www.coolapk.com/apk/top.maweihao.weather

功能还比较简陋,大佬们提提意见~

终于有 Linux 官方的 QQ 了

Posted: 13 Apr 2021 02:54 AM PDT

今天刚刚发现 qq 官网已经有了 linux 版本,快去下载呀 好兄弟们

AWS 该如何从入门到进阶呢

Posted: 13 Apr 2021 02:54 AM PDT

如果没有业务开发场景,纯看文档和视频,纯看博客与讨论,是不是较难深入

推广一个自己写的 grpc-go load balancing 的实现与及改造成自定义 lb 的 github repo

Posted: 13 Apr 2021 02:49 AM PDT

grpc-go load balancing 的官方实现目前仅支持 rr,wrr 的实现好像是个半残品。

鉴于项目的需要,借鉴了 google 上的一些文章、grpc-go 的源码以及 etcd v3.5 的 clientv3 代码编写了此 repo 的代码,地址: https://github.com/xkeyideal/grpcbalance

lb 的实现其实只需要理解 resolver 与 balancer 的 interface 即可随心的改造成自己项目需要的实现方案。

本实现方案是基于 grpc v1.36.0 实现的,看了一下最新的 v1.37.0 与 v1.38.0 接口都是兼容的。

使用方法:

  1. 常规的 lb 方案可直接引用该 repo,特殊要求的 lb 不建议直接引用该 repo,可阅读代码了解原理后根据需求修改;
  2. 本代码没有实现 endpoints 动态变化的部分代码,但 resovler 里提供了 SetEndpoint 方法

希望能帮助有需要的人,enjoy it

在?人在西安,三年后端 Python 渣渣经历,求大佬 review 一下简历

Posted: 13 Apr 2021 02:37 AM PDT

点击这里:个人简历

昨天刚提交了离职,裸辞

github: https://github.com/xcbdjazk

gitee: https://gitee.com/xcbdja

blog: https://maocat.cc

首先感谢 @imdong 大佬的简历模板和思路

说一下个人情况

  • 为什么入了 Python 的坑

    大学自学过 Java,快学到 ssm 时候,选了一个 Python 的毕业设计,后来在西安试着投了下相关岗位,被上家小公司连哄带骗的入职了(说什么公司有多么牛逼的技术,不限制个人技术发展), 后来公司业务急做了半年全栈开发,浪费大半年时间去学前端,2019 年初开始接触 Golang,然后就没有然后了

  • 个人缺点

    上家公司大部分情况下都是用的 MongoDB,Mysql 我大多用在开发自己的小项目和帮人做一些东西,最近在狂补 Mysql 相关的东西

    算法 /数据结构,lc 磨磨唧唧刷了快 100 道题(大多数 easy)

    操作系统 /网络,一塌糊涂,虽然是科班,但我肯定是最差的那种

    英语,一生之敌

    做过的项目都没有深度,没有遇到过高并发的场景(最大的并发量就是数百人在线考试,定时提交答案)

  • 厚着脸的优点

    极强的学习理解能力,曾经只用了两个晚上学了下 ES 就开始上项目,项目中使用到的库也是先使用写个 demo 再运用

    项目的库必要情况下是看过源码,并且加以改造,硬生生将 Flask 做成了 Django

    能够快速理解产品需求,并通过代码实现

    自我感觉很优秀 2018 -> 2021,公司多次主动调薪,4.5k -> 5k -> 8k -> 10k

这阿里云工单我真服

Posted: 13 Apr 2021 02:22 AM PDT

阿里云工单真是太过分了,优先级就算设置成重要,处理的也很慢.还推出一个极速工单,这不是趁火打劫吗

"我的春季战靴太大了" 哈哈哈哈哈哈哈

Posted: 13 Apr 2021 02:20 AM PDT

http://www.voidcn.com/article/p-seyhkavs-bxy.html 春季战靴,这机翻是想笑死我

大家有没有遇到过进程号存在但是进程其实已经死了的情况

Posted: 13 Apr 2021 02:09 AM PDT

stripe atlas 通过审核了

Posted: 13 Apr 2021 01:57 AM PDT

在线签协议的时候有点纠结了,算了下,维护费用 1 年大概要个 6000 左右吧,v2 有开通过的吗,svb 每月大概收多少,我看官网写的是 50 刀

分享一下自己的前端笔记,发现自己简直成了 markdown 程序员...

Posted: 13 Apr 2021 01:34 AM PDT

博客地址

github 地址

= = 顺便求个 star~谢谢大家

群晖神奇的售后

Posted: 13 Apr 2021 01:31 AM PDT

坐标美帝,两个星期前 DS218+突然不开机了。机器是朋友 19 年 2 月买的,后来便宜出给我了。
很不幸坏的时候刚刚过保,抱着试试看的心态提交了一个 ticket,想让朋友走信用卡延保。结果客服回复说机器还在保修期内,没有要购买凭证,让我直接把机器寄回去。经过漫长的等待,今天收到一台带原包装的新机(也有可能是官翻)。
按理说这种东西的保修期都是从第一次联网开始计算的,怀疑是群晖的数据库错乱了...

用 git 踩了个坑

Posted: 13 Apr 2021 01:21 AM PDT

事件顺序

  1. 添加文件 A -- commit1
  2. 一般操作 -- commit2~9
  3. git rm --cached A 并把 A 添加到 gitignore -- commit10
  4. git rebase -i commit2. 保持 commit10 不变
  5. 回放 commit10 时, 文件 A 就丢了...

离开上家公司差不多有半年, 工资还没有发放完!

Posted: 13 Apr 2021 12:56 AM PDT

离开上家公司差不多有半年, 工资还没有发放完, 还有一个多月的工资没发。
离开时还有同事在上班, 现在已经没有人上班了, 但是网站还在运行, 据说是交给合作公司去维护, 这个合作公司在我们还没有入职时就已经跟公司有合作了!

春节前问过公司, 问了多次, 每次都答应在 XXX 前给, 但都没有给, 再问就踢皮球了, 从 X 总到 Y 总, 没办法, 只好组建一个微信群, 把他们全部拉进群, 然后答应说春节前想办法解决, 多少给点钱过节, 但到现在还是没有给, 一分钱都没有。

现在微信群里面已经不回应了, 我打算找劳动局了!
各位 V 友发表下自己的意见

顺便说下, 感觉公司更信任这个合作公司的人。

使用开源的技术计算商场一定时期监控视频中客流量

Posted: 13 Apr 2021 12:42 AM PDT

1 、面对情况:计算 1 个月或半年内商场客流量,主要根据过去 1 个月到半年内几个入口处的监控视频。 2 、主要需求:开源的计算模块;不需要联网,可离线运行;能分析视频中某天特定时间段(比如 9 点以前)最好。形成每天人流量统计表。 》请问有各位大佬有了解的可以解决以上 1 、2 情景的软件或者途径吗?硬件要求多高?欢迎大家讨论分享,先谢过了。

各位大佬,求一个正则。

Posted: 12 Apr 2021 10:22 PM PDT

我正在开发一个前端的类 Excel 计算功能。

这是一个错误的公式,要得出"H4H4H4"、"J3J3J3J3",可能有多个匹配。

=A1+M2-N2+H4H4H4+G7+H5/J3*PREXM('','','')

=A1+M2-N2+H4H4+G7+H5/J3J3J3J3*PREXM('','','')

正确的是这样的:

=A1+M2-N2+H4+G7+H5/J3*PREXM('','','')

请教一个 golang DDD 的数据转化问题

Posted: 12 Apr 2021 10:15 PM PDT

目前想要在服务里面落地 DDD,DDD 里面推荐使用 Entity 和 Value Object 如这篇文章所说: https://www.damianopetrungaro.com/posts/ddd-using-golang-tactical-design/

但是在落地的时候发现数据转化的问题:比如定义了一个 Link Value Object

type Link struct { 	value string }  func (u Link) String() string { 	return u.value }  func NewLink(s string) (URL, error) { 	if match, _ := regexp.MatchString(`^( https?|ftp)://[^\s/$.?#].[^\s]*$`, s); !match { 		return Link{}, fmt.Errorf("project url format is invalid: %v", s) 	} 	return Link{value: s}, nil }   type Project struct { 	ID uint64 	Name string     Url Link } 

然后框架使用 grpc,那么 grpc 本身是有 pb.XXXRequest 这种类型的:

func (s *ServerImpl) Create( 	ctx context.Context,     req *pb.CreateRequest,     res *pb.CreateResponse, ) error { 	url, err := model.NewLink(req.URL)     if err != nil {     	return err     }     //...如果这里有很多都是这种值对象的字段,在这里岂不是很多很多类似     // if err != nil { ... } 这样的代码吗?而且这样手工转也比较麻烦 	project := model.Project{     	ID: req.ID,         Url: url     } } 

各位遇到这样的问题有没有什么比较好的比较优雅的方式来解决?

HPE gen10+ 4k 软解有结论吗?忍不住要入一台

Posted: 12 Apr 2021 10:08 PM PDT

本来以经有白裙了,对 gen10+没啥兴趣,但是机器可以人肉带回,有点按耐不住
目前的问题不能忍是核显被屏蔽不能硬解 4K,唯一的 pci 打算留给万兆网卡,CPU 似乎不得不换,不知道软解的话有没有问题,哪款比较合适,高配的话性价比不高

Android12 和手机淘宝的问题。

Posted: 12 Apr 2021 09:12 PM PDT

最新开发者预览版 Android12 和手机淘宝最新版。

包括淘宝 Lite,淘宝特价版,和国内商店的淘宝。

在有无 root 的环境分别尝试。

手机淘宝加载某些商品详情页会崩溃。

之间搜索品牌名称会崩溃。

使用内置小程序会崩溃。

进入设置-反馈页面会崩溃。

与客服聊天会崩溃。

求教一个 API 设计难题

Posted: 12 Apr 2021 09:03 PM PDT

最近在写一个应用,涉及到几个外部数据源的操作,API 设计上有一些矛盾,大家觉得哪种好,还是有其他的设计?

  1. 创建数据源
POST /data-source 
  1. 获取支持的数据源类型列表
// 感觉 URL 太长 GET /data-source-type  // 跟 GET /data-source/{id} 重叠了 GET /data-source/types 
  1. 提供连接参数,检测数据源是否可用
POST /data-source-check POST /data-source?action=check 
  1. 创建之前初始化数据源,比如创建 MySQL 表
POST /data-source-init POST /data-source/init POST /data-source?action=init 

总结来说就是 对象未创建之前进行的一些操作怎么设计,比如:

检查用户是否存在 vs 创建一个用户

ppt 调试法

Posted: 12 Apr 2021 08:13 PM PDT

最近招了好些新人,发现一些共同问题。

开发过程中,出现问题,诊断排查没有章法,非常耗时。自己很受挫,绩效也很低。

首先明确一点,绩效低是错的。不能无休止的黑灯瞎火去所谓的解决问题。其实毫无绩效。我们只看结果的。如果过程不对导致绩效低,那是要批评的。

我们有个原则,30 分钟没有头绪,务必整理问题分析报告文档。

这个分析报告文档,是 ppt 格式,从现象出发,检查时间点的日志,并分析日志。

如果没有日志,就需要补充日志。如果条件允许,可以打上短点,直接疑点代码的执行逻辑为什么不合理。

如果是底层出错,对日志不明白,就需要搜索检索。搜索的时候,一定注意搜索英文站点,可以通过 bing 来搜索。

日志的分析,需要明确问题的故障点。我们需要回到设计领域,明确系统架构工作原理,这样方便分析问题到底在哪里。

明确故障点,通常采用采用折半查找法,对每个接口数据的输入输出进行检查,看看是否正常。这个折半查找其实和维修家用电器差不多,对电路每个节点检查,看看电压波形输入输出是不是正常。只是在软件中的接口是数据,需要经常接口数据是否有问题。如果有问题,就往源头方向查,最终定位到代码。

所以要排查定位问题,需要理解系统架构,需要学会查看前后端各种日志,需要明确接口含义。

所有这个分析过程,都需要记录在 ppt 上,边分析边记录,好脑筋不如烂笔头。记录下来,一方面是方便自己回顾分析,不至于在各种问题现象中迷失错乱。另外一方面,如果不能解决,可以拿着这个排查报告求助他人,可以高效得到支持。因为任何一个分析失误,都可能引导到错误方向,空对空说自己的分析结论毫无意义,必须看原始现象日志才能做出结论。

排斥解决问题,是作为开发人员首先必须过关的一个技能,这是作为职业工程师的第一步。必须学会固化这个套路,这样才能建立战胜问题的信心,才能提高工作效率,才能进入追求卓越的正循环。

很多人被问题打败,甚至觉得自己不是做这一行的,对问题产生惧怕,看到问题慌乱,这是走向崩溃的负面。必须严格基于上面的套路来做,及时寻求帮助,不断高效解决问题,才能重获信心,重新进入追求卓越正循环。

有什么办法记录下 Linux 执行过的 history 命令

Posted: 12 Apr 2021 03:41 PM PDT

记录下来 history,避免 history -c 或者其他命令清空执行历史

想深入了解一下 K8S,请问有什么好的渠道?

Posted: 12 Apr 2021 12:54 PM PDT

目前做基于 K8S Python API 的开发,和 K8S 集群的运维,用到的技术都是非常简单的,比如应用都是常规的 Deployment+Service,公司开发的项目没有用 StatefulSet 的,没有用共享存储比如 Ceph 、Gluster 等,没有用到 IngressControler,没有用到自定义的 Operator,平时遇到的问题也都比较常规。想再深入了解一下 K8S 各个组件的一些具体的实现,能熟悉更多资源类型,并且更熟悉 K8 的网络架构等。大家有啥好的资源推荐吗?书、博客、视频都 OK 。十分感谢!

windows 平台 c++如何简单安全的实现多进程多线程读写同一个文件

Posted: 12 Apr 2021 12:41 PM PDT

大家好,请教一下各位大佬 多进程多线程同时读写同一个 json 配置文件 怎么样才能既简单又安全的读写,保证读写成功,配置文件不丢失不错乱 或者有这方面的轮子吗?谢谢😉

V 站有从事咨询的吗?你是如何走上咨询的道路的呢

Posted: 12 Apr 2021 11:13 AM PDT

咨询顾问给人的感觉不仅是有很多理论,而且也有技术实践,感觉是比较好的一种职业追求
除产品思维外,我觉得咨询思维方式也应该程序员学习的

能否在华为系统中加入一个开机自启动的自动投屏脚本?

Posted: 12 Apr 2021 08:10 AM PDT

手机屏要坏了 但是有个英语单词软件转移不出来 能不能搞一个脚本 开机自动运行把手机屏幕投到特定的电脑上?

對於目前網路上各式各樣的帳號密碼,有沒有甚麼方便又易用的管理方式?

Posted: 12 Apr 2021 05:57 AM PDT

有些網路服務需要定期更新密碼,有的帳號和密碼有特殊的要求,不知道各位有沒有甚麼好用的辦法來管理和生成帳號和密碼?

No comments:

Post a Comment