wq's blogs

王乾


  • 首页

  • 分类

  • 标签

  • 归档

Mac下配置.bash_profile(环境变量)

发表于 2018-09-10 | 分类于 Golang基础

最近开始学习Golang,在调试程序时报错,然后为了解决错误不小心改了.bash_profile这个文件,也就是配置环境变量,结果导致终端很多基本命令都不能使用,在网上找到一些解决办法,亲测有效。

1、在命令行中输入:

export PATH=/usr/bin:/usr/sbin:/bin:/sbin:/usr/X11R6/bin

这样可以保证命令行命令暂时可以使用。命令执行完之后先不要关闭终端。
如果你的命令行命令可以使用,请直接跳到第2步。

2、进入当前用户的home目录:

cd ~/

3、创建.bash_profile文件:

touch .bash_profile

4、 打开.bash_profile并编辑:

open .bash_profile

5、这样就打开了一个记事本,会显示你之前配置过的path,修改记事本,强烈建议先备份下,然后根据自己需要配置。

JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_161.jdk/Contents/Home
PATH=$JAVA_HOME/bin:$PATH:.
CLASSPATH=$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:.
export JAVA_HOME
export PATH
export CLASSPATH
export GOPATH=/Users/wangqian/Desktop/Golang_Study
export GOROOT=/usr/local/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN

上面是我配置的Java环境和golang环境

6、command+s保存关闭文件

7、使修改后的配置生效命令:

source .bash_profile

8、验证环境变量是否配置成功

如果是java,在终端输入以下命令

java -version

Mac环境下安装、配置golang

发表于 2018-09-02 | 分类于 Golang基础

1、下载

1、国内镜像下载地址:https://golang.google.cn/dl/
2、终端中输入go ,若出现下图即安装成功。

Go is a tool for managing Go source code.

Usage:

go <command> [arguments]

The commands are:

bug         start a bug report
build       compile packages and dependencies
clean       remove object files and cached files
doc         show documentation for package or symbol
env         print Go environment information
fix         update packages to use new APIs
fmt         gofmt (reformat) package sources
generate    generate Go files by processing source
get         download and install packages and dependencies
install     compile and install packages and dependencies
list        list packages or modules
mod         module maintenance
run         compile and run Go program
test        test packages
tool        run specified go tool
version     print Go version
vet         report likely mistakes in packages

Use "go help <command>" for more information about a command.

Additional help topics:

buildmode   build modes
c           calling between Go and C
cache       build and test caching
environment environment variables
filetype    file types
go.mod      the go.mod file
gopath      GOPATH environment variable
gopath-get  legacy GOPATH go get
goproxy     module proxy protocol
importpath  import path syntax
modules     modules, module versions, and more
module-get  module-aware go get
packages    package lists and patterns
testflag    testing flags
testfunc    testing functions

Use "go help <topic>" for more information about that topic.

3、开发环境构建:通过go version查看版本,在1.8版本前必须设置这个环境变量。1.8版本后(含1.8)如果没有设置使用默认值

在 Unix 上默认为 $HOME/go 
在 Windows 上默认为 %USERPROFILE%/go 
在 Mac 上 GOPATH 可以通过修改 ~/.bash_profile 来设置

2、测试是否安装成功

新建源码文件hello.go

cd /Users/wangqian/Desktop/Golang_Study/src  //打开源文件存放的位置
vim hello.go   // 编辑hello.go文件

编码hello.go文件:

package main
import "fmt"

func main(){
fmt.Printf("hello world\n")
}

退出保存后直接运行

go run hello.go

wangqiandeMacBook-Pro:src wangqian$ go run hello.go
hello world

现在我们把源文件编译成二进制文件,并且运行当前二进制文件

go build -ldflags "-s -w" -o hi.out

wangqiandeMacBook-Pro:src wangqian$ go build -ldflags "-s -w" -o hi.out
wangqiandeMacBook-Pro:src wangqian$ ./hi.out
hello world

这样在当前文件夹中就会存在一个源文件,一个编译文件

3、go常用命令介绍

go run 路径需要完整的路径到src
wangqiandeMacBook-Pro:Golang_Study wangqian$ go run src/day_01/hello_world.go

hello world

wangqiandeMacBook-Pro:Golang_Study wangqian$ go run day_01/hello_world.go

stat day_01/hello_world.go: no such file or directory

go build 编译的时候制定固定的包就行了,不需要带上src
go build day_01 go build 是在当前文件路径生成可执行文件,
go build -o bin/hello2 day_01 指定在bin路径下生成名称hello2的可执行文件

go install day_01 生成可执行文件在bin目录下
前提是go环境bin路径修改过 GOBIN=”/Users/wangqian/Desktop/Golang_Study/bin”

go fmt day_01 格式化代码 直接包名路径就行

在VSCode中目录结构如下图所示:

4、设置GOPATH环境变量

开始写 go 项目代码之前,需要我们先配置好环境变量。编辑 ~/.bash_profile(在终端中运行 vi ~/.bash_profile 即可)来添加下面这行代码(如果你找不到 .bash_profile,那自己创建一个就可以了)

export GOPATH=$HOME/go

保存然后退出你的编辑器。然后在终端中运行下面命令

source ~/.bash_profile

提示:$HOME是每个电脑下的用户主目录,每个电脑可能不同,可以在终端运行 echo $HOME 获取
GOROOT 默认是在 /usr/local/go,如果没有,可以在 bash_profile 文件中设置。
export GOROOT=/usr/local/go
然后保存并退出编辑器,运行 source ~/.bash_profile 命令即可

GitHub Desktop 链接 码云、GitLab使用方法

发表于 2018-09-01 | 分类于 工具

1、添加SSH私钥并连接

1、ssh-add /Users/wangqian/id_rsa 
    /Users/wangqian/id_rsa 为私钥的地址
2、ssh -T git@gitlab.ttsing.com

当出现 Welcome to GitLab, wq! 表示连接成功

2、如何从码云、GitLab导入到GitHubDeskTop桌面工具

1、先用命令行切换到本地的目录。
2、使用git clone 码云GIT地址 命令将项目克隆到本地。
3、在GitHub Desktop上添加(Add)本地项目(local path)。
4、在GitHub Desktop上尽情地提交、同步吧!

3、如何将本地的项目上传到码码云、GitLab

1、选择本地目录,在GitHub Desktop上添加本地项目。
2、在码云GIT上新建项目。
3、 命令行使用git remote add origin GIT地址 将本地项目与码云GIT项目建立关系。
4、先使用命令git pull origin master 同步代码。
5、使用命令git push origin master 将本地代码推送到远程项目。
6、在GitHub Desktop上尽情地提交、同步吧!

Markdown基本语法

发表于 2018-08-29 | 分类于 工具

Markdown是一种纯文本格式的标记语言。通过简单的标记语法,它可以使普通文本内容具有一定的格式。

1、标题

在想要设置为标题的文字前面加#来表示
一个#是一级标题,二个#是二级标题,以此类推。支持六级标题。
示例:

# 这是一级标题
## 这是二级标题
### 这是三级标题
#### 这是四级标题
##### 这是五级标题
###### 这是六级标题

效果如下:

2、字体

加粗 - 要加粗的文字左右分别用两个*号包起来

斜体 - 要倾斜的文字左右分别用一个*号包起来

斜体加粗 - 要倾斜和加粗的文字左右分别用三个*号包起来

删除线 - 要加删除线的文字左右分别用两个~~号包起来

修改字体颜色 - 字体改成红色了
示例:

**这是加粗的文字**
*这是倾斜的文字*
***这是斜体加粗的文字***
~~这是加删除线的文字~~
<font color=红色> 字体改成红色了 </font>

效果如下:

3、引用

在需要引用的文字前加>即可。
示例:

>这里是引用的内容
>>这里是引用的内容

效果如下:

4、分割线

三个或者三个以上 - 或者 * 都可以
示例:

---
----
***
****

5、图片

![图片alt](图片地址 ''图片title'')

图片alt就是显示在图片下面的文字,相当于对图片内容的解释。
图片title是图片的标题,当鼠标移到图片上时显示的内容。title可加可不加

6、超链接

[超链接名](超链接地址 "超链接title")
title可加可不加

示例:

[百度](http://baidu.com)

效果如下:

百度

7、表格

语法如下:

表头|表头|表头
---|:--:|---:
内容|内容|内容
内容|内容|内容

第二行分割表头和内容。
- 有一个就行,为了对齐,多加了几个
文字默认居左
-两边加:表示文字居中
-右边加:表示文字居右
注:原生的语法两边都要用 | 包起来。此处省略

示例:

姓名|技能|排行
--|:--:|--:
刘备|哭|大哥
关羽|打|二哥
张飞|骂|三弟

效果如下:

姓名 技能 排行
刘备 哭 大哥
关羽 打 二哥
张飞 骂 三弟

标识符、关键字、变量

发表于 2018-08-16 | 分类于 Golang基础

1、标识符和关键字

标识符 :Go语言的代码中的几乎所有东西都有一个名称或标识符
_本身就是一个特殊的标识符,被称为空白标识符.它可以像其他标识符那样用于变量的声明或赋值(任何类型都可以赋值给它),但任何赋给这个标识符的值都将被抛弃

关键字:Go中25个关键字或保留字。(var、if之类)
和其它语言一样,关键字不能够作标识符使用。

预定义标识符:Go 语言还有 36 个预定义标识符,其中包含了基本类型的名称和一些基本的内置函数(int32之类)

2、变量的声明

Go语言是静态类型语言,在检查函数调用中编译器检查变量类型的正确性,因此变量必须有明确的类型。在数学概念中,变量表示没有固定值且可改变的数。但从计算机系统实现角度来看,变量是一段或多段用来存储数据的内存。

当一个变量被声明之后,系统自动赋予它该类型的零值:int 为 0,float 为 0.0,bool 为 false,string 为空字符串,指针为 nil 等。所有的内存在 Go 中都是经过初始化的。(实例变量存在堆中,默认初始化值)

数据类型:基本数据类型和引用数据类型

GO语言基本数据类型:

string

bool

int(32系统占4字节,64位系统占8字节)、int8(一个字节)、int16、int32 (rune)、int64

uint(32系统占4字节,64位系统占8字节)、uint8(byte)、uint16、uint32、uint64、uintptr

float32、float64

complex64、complex128 complex复杂的

注意:
Golang在没声明具体整型时,默认为int;
Golang在没声明具体浮点型时,默认为float64

标准格式

声明变量的一般形式是使用 var 关键字:var identifier type

批量格式

1    var (
2        a int
3        b string
4        c []float32
5        d func() bool
6        e struct {
7            x int
8        }
9    )

简短格式

1    func main() {
2       x:=100
3       a,s:=1, "abc"
4    }

需要注意的是,简短模式(short variable declaration)有以下限制:

  • 只能用在函数内部
  • 不能提供数据类型。
  • 定义变量,同时显式初始化。

匿名变量的特点是一个下画线“_”,“_”本身就是一个特殊的标识符,被称为空白标识符

特点:

1、可以像其他标识符那样用于变量的声明或赋值,但任何赋给这个标识符的值都将被抛弃

2、值不能在后续的代码中使用,也不可以使用这个这个标识符作为变量对其它变量的进行赋值或运算

3、匿名变量不占用命名空间,不会分配内存。匿名变量与匿名变量之间也不会因为多次声明而无法使用。

iOS单例模式,你真的写对了吗?

发表于 2017-08-23 | 分类于 iOS开发技巧

单例类的生命周期

单例实例在存储器的中位置

请看下面的表格展示了程序中中不同的变量在手机存储器中的存储位置;

在程序中,一个单例类在程序中只能初始化一次,为了保证在使用中始终都是存在的,所以单例是在存储器的全局区域,在编译时分配内存,只要程序还在运行就会一直占用内存,在APP结束后由系统释放这部分内存内存。

单例模式很常见,但是,能真正把单利模式写对的却很少。在iOS中,一般我们都是用官方推荐的写法来写单例:

+ (instancetype)sharedInstance {

    static WQSQLiteManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[WQSQLiteManager alloc] init];
    });
    return instance;
}

这也是我们单例模式的标准写法。 在使用时,我们只需要

WQSQLiteManager *manager = [WQSQLiteManager sharedInstance];

问题:

可是,在多人开发中,并不能保证所有人都会使用 sharedInstance 方法来创建对象;而一旦有人用 alloc,new 等来创建对象,这就不是单例了。例如:

WQSQLiteManager *a = [WQSQLiteManager sharedInstance];
WQSQLiteManager *b = [[WQSQLiteManager alloc] init];
WQSQLiteManager *c = [WQSQLiteManager new];

让我们来打印 a、b、c内存地址:

a:<WQSQLiteManager: 0x600001f1fdf0>
b:<WQSQLiteManager: 0x600001f1fe00>
c:<WQSQLiteManager: 0x600001f1fe10>

可以看出, a、b、c 不是同一个对象,而所谓单例,就是不管我用何种方法创建对象,都必须是同一个。所以,单例模式,绝不是一个 sharedInstance 就够了。

方案一

那么如何避免这种问题呢?我们知道:在对象创建的时候,alloc、new都会调用到 allocWithZone: 方法;使用拷贝创建对象时,会调用 copyWithZone: 、mutableCopyWithZone:方法;那么,重写这些方法,就可以让创建的对象唯一。

+ (instancetype)sharedInstance {

    static WQSQLiteManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
    //   instance = [[WQSQLiteManager alloc] init];

   instance = [[super allocWithZone:nil] init];
});
    return instance;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone {
    return [WQSQLiteManager sharedInstance];
}
- (instancetype)copyWithZone:(NSZone *)zone {
    return [WQSQLiteManager sharedInstance];
}
- (instancetype)mutableCopyWithZone:(NSZone *)zone     {
        return [WQSQLiteManager sharedInstance];
}

再运行,看一看a、b、c:

a:<WQSQLiteManager: 0x60000331d690>
a:<WQSQLiteManager: 0x60000331d690>
a:<WQSQLiteManager: 0x60000331d690>

初始化一个对象的时候,[[Class alloc] init],其实是做了两件事。
alloc 给对象分配内存空间,init是对对象的初始化,包括设置成员变量初值这些工作。
而给对象分配空间,除了alloc方法之外,还有另一个方法: allocWithZone.
使用alloc方法初始化一个类的实例的时候,默认是调用了allocWithZone的方法

方案二

还有一种方法,就是直接禁用掉 alloc、new 、copy等方法:

// 告诉编译器该方法不可用,如果强行调用编译器会提示错误
+ (instancetype)alloc UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new __attribute__((unavailable("replace with 'sharedInstance'")));
- (instancetype)copy __attribute__((unavailable("replace with 'sharedInstance'")));
- (instancetype)mutableCopy __attribute__((unavailable("replace with 'sharedInstance'")));


+ (instancetype)sharedInstance {

static WQSQLiteManager *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{

    //instance = [[WQSQLiteManager alloc] init];

    instance = [[super allocWithZone:nil] init];
});
return instance;
}

那么,在调用这些方法的时候就会报错,

以此达到单例模式的要求,始终只有一个对象。

Objective-C中的各种遍历方式

发表于 2017-08-21 | 分类于 iOS开发技巧

1、使用for循环

要遍历字典、数组或者是集合,for循环是最简单也用的比较多的方法,示例如下: 

// 数组
NSArray *array = @[@"1",@"2",@"3",@"4"];
for (int i = 0; i < array.count; i ++) {
    NSString *obj = array[i];
    NSLog(@"%@",obj);
}

//  字典
NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
NSArray *dictKeysArray = [dictM allKeys];
for (int i = 0; i<dictKeysArray.count; i++) {
    NSString *key = dictKeysArray[i];
    NSString *obj = [dictM objectForKey:key];
    NSLog(@"%@:%@",key,obj);
}

// 集合(无序、不能重复 其他和Array一样)
NSSet *set = [NSSet setWithObjects:@"1",@"2",@"3",@"4", nil];
for (NSInteger index = 0; index < set.allObjects.count; index ++) {
    NSString *obj = set.allObjects[index];
    NSLog(@"%@",obj);
}

// 反向遍历(以数组为例子)
NSArray *array2 = @[@"1",@"2",@"3",@"4"];
for (NSInteger index = array2.count - 1; index >= 0; index --) {
    NSLog(@"%@",array2[index]);
}

优点:简单

缺点:由于字典和集合内部是无序的,导致我们在遍历字典和集合的时候需要借助一个新的“数组”作为中介来处理,多出了一部分开销。

2、使用for…in循环

在Objective-C 2.0 中增加了for …In 形式的快速遍历。此种遍历方式语法简洁,速度飞快。示例如下:

// 数组
NSArray *array = @[@"1",@"2",@"3",@"4"];
for (id obj in array) {
    NSLog(@"%@",obj);
}

//  字典
NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
for (id obj in dictM) {
    NSLog(@"%@",dictM[obj]);
}

// 集合(无序、不能重复 其他和Array一样)
NSSet *set = [NSSet setWithObjects:@"1",@"2",@"3",@"4", nil];
for (id obj in set) {
    NSLog(@"%@",obj);
}

// 反向遍历(以数组为例子)
NSArray *array2 = @[@"1",@"2",@"3",@"4"];
for (id obj in [array2 reverseObjectEnumerator]) {
    NSLog(@"%@",obj);
}

优点:1)语法简洁;2)效率最高;

缺点:无法获得当前遍历操作所针对的下标。

3、使用NSEnumerator遍历

NSEnumerator的使用和基本的for循环类似,不过代码量要大一些。示例如下:

// 数组
NSArray *arrayM = @[@"1",@"2",@"3",@"4"];
NSEnumerator *arrayEnumerator = [arrayM objectEnumerator];
NSString *obj;
while ((obj = [arrayEnumerator nextObject]) != nil) {
    NSLog(@"%@",obj);
}

// 字典
NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
NSEnumerator *dictEnumerator = [dictM keyEnumerator];
NSString *key;
while ((key = [dictEnumerator nextObject]) != nil) {
    NSString *obj = dictM[key];
    NSLog(@"%@",obj);
}

// 集合(无序、不能重复 其他和Array一样)
NSSet * setM = [[NSSet alloc] initWithObjects:@"one",@"two",@"three",@"four", nil];
NSEnumerator *setEnumerator = [setM objectEnumerator];
NSString *setObj;
while ((setObj = [setEnumerator nextObject]) != nil) {
    NSLog(@"%@",setObj);
}


// 反向遍历(以数组为例子)
NSArray *arrayM2 = @[@"1",@"2",@"3",@"4"];
NSEnumerator *arrayEnumerator2 = [arrayM2 reverseObjectEnumerator];
NSString *obj2;
while ((obj2 = [arrayEnumerator2 nextObject]) != nil) {
    NSLog(@"%@",obj2);
}

优点:对于不同的数据类型,遍历的语法相似;内部可以简单的通过reverseObjectEnumerator设置进行反向遍历。

缺点:代码量稍大。

4、基于Block的遍历方式

基于Block的方式来进行遍历是最新引入的方法。它提供了遍历数组|字典等类型数据的最佳实践。示例如下:

// 数组
NSArray *array = @[@"1",@"2",@"3",@"4"];
[array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    NSLog(@"%lu--%@",(unsigned long)idx,obj);
}];

//  字典
NSDictionary *dictM = @{@"1":@"one",@"2":@"two",@"3":@"three"};
[dictM enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
    NSLog(@"%@:%@",key,obj);
}];

// 集合(无序、不能重复 其他和Array一样)
NSSet *set = [NSSet setWithObjects:@"1",@"2",@"3",@"4", nil];
[set enumerateObjectsUsingBlock:^(id  _Nonnull obj, BOOL * _Nonnull stop) {
    NSLog(@"%@",obj);
}];

// 反向遍历(以数组为例子)
NSArray *array2 = @[@"1",@"2",@"3",@"4"];
[array2 enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
    NSLog(@"%zd--%@",idx,obj);
}];

优点:1)遍历时可以直接从block中获得需要的所有信息,包括下标、值等。特别相对于字典而言,不需要做多余的编码即可同时获得key和value的值。

   2)能够直接修改block中key或者obj的类型为真实类型,可以省去类型转换的工作。

   3)可以通过NSEnumerationConcurrent枚举值开启并发迭代功能。

说明:基于Block的遍历方式在实现反向遍历的时候也非常简单,使用enumerateObjectsWithOptions方法,传递NSEnumerationReverse作为参数即可,在处理遍历操作的时候推荐基于Block的遍历方式。

5、使GCD中的dispatch_apply函数

使用GCD中的dispatch_apply函数也能实现字典、数组等的遍历,该函数比较适合处理耗时较长、迭代次数较多的情况。示例如下:

NSArray *array3 = @[@"10",@"11",@"12",@"13",@"14"];
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(array3.count, queue, ^(size_t index) {
    NSLog(@"%@--%@",array3[index],[NSThread currentThread]);
});

优点:开启多条线程并发处理遍历任务,执行效率高。

缺点:1)对于字典和集合的处理需借助数组;2)无法实现反向遍历。

123
王乾

王乾

在成为最厉害最厉害最厉害的道路上。

27 日志
4 分类
5 标签
RSS
GitHub E-Mail
© 2020 王乾