很久没有参与过面试了,本着不能与市场脱节的原则,上周四打开BOSS直聘以后就收到很多的面试邀请,其中也有原老东家,还有很多小公司,当然还有本次复盘的蔚来。

上周五下午看到蔚来HR发来的面试邀请,本来没想着去面试,一来因为离家有点远,二来自己对Android开发确实有点手生了,但考虑蔚来确实是合肥本土比较有实力的公司,还是希望能了解下蔚来的技术栈,所以下午给蔚来HR发了简历,接着周一下午就接到上海打过来的电话,当时我还在客户公司洽谈业务,中断下接了电话确认周二(12月7日)下午5点的视频面试。

周二一早到公司,网上简单看了下Android最新的版本特性,像是 Jetpack Compose ,这个是官方新推的组件,还有一些kotlin的新特性之类的,就没有回顾数据结构和Java相关的内容,事后想来这确实是我自己没有深入考虑,从面试完的感觉来看,蔚来的面试官问了很多Java相关的和几个数据结构相关的问题,这部分内容后来上github搜的时候发现全都是 Android-Daily-Interview 里面的东西,面试官应该也是从网上找的题目来提问,毕竟这样最省事也最容易让面试官掌握主动权。

从面试快结束和面试官的沟通过程中了解到,蔚来车机娱乐App相关的技术栈还是原生Java为主,也没有提到Jetpack相关的内容,说明还是偏传统向的,这个在前面也提到我没有深入考虑的原因,因为从技术上来说,都能实现的内容,作为车机厂商肯定会力求不要大的改动,一旦引入新的技术或者改动较大带来的是测试工作的不确定性,从项目角度包括研发负责人的角度考虑,一般也不会太主动推进新技术的落地。这和华米的技术路线截然相反,前几天和在华米的前同事聊天,他们对于Android新技术的推进非常积极,甚至有点激进。这其实还是和公司的性质有关系,华米本质上是一家面向消费市场的潮流型公司,必须不断的提供最新的效果,同时要考虑不断迭代的新机型和新技术方案。

一家公司对技术的保守还是创新主要取决于业务需求以及产品的复杂度,和企业的规模大小无关,所以针对不同的公司,作为一个面试者需要提前预判将要面试公司的技术栈,然后做对应的准备,这样才能在这个卷的不行的面试中答题通过,毕竟我们都知道“面试造火箭,上班拧螺丝”。我作为一个曾经的面试官是极力不认同这种面试行为,因为作为面试来说主要考察是以后业务上是不是能胜任以及逻辑是否清晰,面试筛选的是能在以后的工作中完成需求和解决问题的人,而不是熟背题目的卷王。

最近在使用Golang集成虹软Linux SDK时,发现不能单纯的设置CGO_ENABLED=0,这样会导致C/C++库调用出错,无法完成正常的编译,因为你需要引入C/C++库的时候,不能禁用CGO。

而且虹软Linux SDK只能在Linux平台编译,macOS上缺少必须的glibc库,所以使用Docker是最好的方案,好在Docker社区的强大,几乎你需要的所有环境都有对应的官方镜像,这里推荐golang:alpine作为基础镜像,这个镜像包含了基础的Golang运行环境和可供编译C/C++的Linux环境,如果有缺少的参数可以自行添加。

为了减少最终镜像体积,可以分阶段构建,大概的Dockerfile如下:

# 使用基础镜像构建
FROM golang:1.15-alpine AS build
RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories
RUN apk add libc6-compat libgcc libstdc++
ENV GO111MODULE=on \
    GOPROXY=https://goproxy.cn,direct \
    GOOS=linux \
    GOARCH=amd64
WORKDIR /build
COPY lib /usr/
COPY go.mod .
COPY go.sum .
RUN go mod download
COPY . .
RUN go build -o face
# 使用轻量化镜像运行减少体积
FROM scratch as final
ENV TZ=Asia/Shanghai
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /usr/share/zoneinfo /usr/share/zoneinfo
COPY --from=build /build/face /
COPY --from=build /build/.env /face.env
ENTRYPOINT ["/face"]

最近一个项目使用Docker来部署的,但每次手动部署都需要先把代码拉取到本地,然后在执行命令删除原来的容器和镜像,最后再部署,非常繁琐,所以直接把这些命令放在一个Shell脚本内,实现一键部署,代码如下:

# 指定代码目录
codePath="/root/";
# 接收输入,形如:  xxx.sh projectName
project=$1;
if [ ! -n "$1" ] ;then
  projectName="projectName";
fi
cd $codePath$projectName
echo "git pull start" ;
# 拉取最新代码
git pull origin master
echo "git pull finish" ;

echo "Docker build start" ;
# 停止容器、删除容器、删除镜像
docker stop app
docker rm app
docker image rm app
docker build . -t app
echo "Docker build finish" ;

echo "Docker deploy start" ;
# 开始部署
docker run -d --name app --network host --restart=always -v ~/app.env:/app.env app
echo "Docker deploy finish" ;

自此一个半自动部署脚本完成,后续有时间再把脚本和Jenkins集成到一起,就可以实现定时或者提交后自动部署了。

最近在使用Golang开发数据库操作过程中,涉及到PostgreSQL的主键自增长,一般在MySQL中可以使用AUTO_INCREMENT字段来实现主键自增长,语句如下:

CREATE TABLE IF NOT EXISTS `table_name`(
   `id` INT UNSIGNED AUTO_INCREMENT,
   `title` VARCHAR(100) NOT NULL,
   `author` VARCHAR(40) NOT NULL,
   `sub_date` DATE,
   PRIMARY KEY ( `id` )
)ENGINE=InnoDB DEFAULT CHARSET=utf8;

但在PostgreSQL中无法使用AUTO_INCREMENT,经过查询得知PostgreSQL需要使用序列来标识字段的自增长,语句如下:

#先创建序列
CREATE SEQUENCE upms_id_seq START 1;

#主键赋默认值
CREATE TABLE "table_name" (
  "id" int4 NOT NULL DEFAULT nextval('upms_id_seq'),
  "title" varchar(100) NOT NULL,
  "author" varchar(40) NOT NULL,
  "sub_date" timestamptz,
  PRIMARY KEY ("id")
);

最近给服务器拷贝文件,由于文件较大,网络传输较慢,所以想到拿U盘拷贝,由于macOS、Windows、Linux系统之间文件格式互不兼容,所以搜了下哪种格式最适合,于是让我找到了UDF格式,具体的格式内容可以参考维基百科 - Universal Disk Format

由于各种Windows和macOS格式化会存在兼容问题,所以推荐在macOS或Linux环境下使用开源工具进行格式化
https://github.com/JElchison/format-udf
查看挂载硬盘,找到你那个U盘,形如/dev/sdb、/dev/disk2这样的,然后再执行格式化。

fdisk -l  #我电脑显示/dev/disk2,以disk2为例
./format-udf.sh /dev/disk2 "My UDF External Drive"

格式化以后,插入macOS和Windows会自动识别U盘,插入Linux系统需要新建个目录并执行挂载命令。

mkdir /mnt/usb
mount -t udf /dev/sdb /mnt/usb

使用完以后,macOS和Windows需要弹出U盘,Linux执行卸载命令才可以拔掉,否则会造成数据丢失。

umount /dev/sdb