FormFile获取到的File如何解压

有问必答Xanthus 回复了问题 • 3 人关注 • 2 个回复 • 121 次浏览 • 2017-05-15 20:34 • 来自相关话题

【上海招聘】golang后端工程师

招聘应聘philfish 发表了文章 • 0 个评论 • 140 次浏览 • 2017-05-15 17:20 • 来自相关话题

职位名称:golang游戏后端工程师

月薪待遇:8000-18000元

招聘人数:2人

工作经验:一年

工作地点:浦东新区碧波路635号传奇广场13 - 15室

收取简历邮箱:查看全部

职位名称:golang游戏后端工程师


月薪待遇:8000-18000元


招聘人数:2人


工作经验:一年


工作地点:浦东新区碧波路635号传奇广场13 - 15室


收取简历邮箱:172971005@qq.com


任职要求:


1、熟悉golang编程语言。


2、熟悉TCP/IP网络协议及其相关的网络编程模型;熟悉http。


3、有良好的语言沟通能力、团队合作能力。

GoCN每日新闻(2017-05-15)

回复

文章分享astaxie 发起了问题 • 1 人关注 • 0 个回复 • 223 次浏览 • 2017-05-15 13:19 • 来自相关话题

[招聘 golang] 北京与你科技有限公司

招聘应聘blackbeans 发表了文章 • 0 个评论 • 980 次浏览 • 2017-05-15 10:56 • 来自相关话题

北京与你科技有限公司( https://www.uneed.com/)

“与你游戏”将会做一个与众不同的休闲游戏中心,我们有原创的能力,这是最难的地方,同时也是最核心... 查看全部

北京与你科技有限公司( https://www.uneed.com/)


“与你游戏”将会做一个与众不同的休闲游戏中心,我们有原创的能力,这是最难的地方,同时也是最核心的竞争力。公司由原陌陌CTO李志威创立,一家有较高起点,但态度踏实的公司。
我们的应用:


与你游戏:


AppStore: https://itunes.apple.com/ph/app/yu-ni-you-xi/id1194906154?mt=8#


Android: http://cdn.uneed.com/web/apk/uneed_released.apk


招聘 golang 工程师一枚。


我们没有非常沉重的历史包袱,所以可以轻盈的奔跑;并且不会再再过每天修修补补的搬砖生活,不用再每天担心为前人的坑背锅,总之一切都是好的。当然我们要求你要求学习能力强,具有良好的编程风格。招聘么,当然要要个正式的jd的样子,那么就请看下面的介绍吧.


岗位描述:


负责与你游戏服务器端api、即时通讯部分的开发

技能要求:


1.至少熟练掌握 Java/Php 一种语言,并且有意向专向 Golang


2.了解分布式服务的基本原理及架构


3.熟悉 MySQL、Redis 配置、维护、性能优化,并有良好的数据库设计能力


4.熟悉 TCP、UDP、HTTP 等网络协议


5.熟悉 Golang 的优先录用


面试通过宝典:(https://github.com/blackbeans)


简历请投递掉 zhao.chao@uneed.com

GoCN每日新闻(2017-05-14)

回复

文章分享astaxie 发起了问题 • 1 人关注 • 0 个回复 • 274 次浏览 • 2017-05-14 11:33 • 来自相关话题

GoCN每日新闻(2017-05-13)

回复

文章分享astaxie 发起了问题 • 3 人关注 • 0 个回复 • 240 次浏览 • 2017-05-13 12:25 • 来自相关话题

VSCODE 使用 delv 有遇到 Cannot read property 'currentGoroutine' of null 错误吗?

回复

有问必答chenhui7373 回复了问题 • 1 人关注 • 1 个回复 • 202 次浏览 • 2017-05-12 17:03 • 来自相关话题

问题已经解决

回复

有问必答kakashi 发起了问题 • 1 人关注 • 0 个回复 • 150 次浏览 • 2017-05-12 13:32 • 来自相关话题

【上海】Strikingly (YC W13) 招聘 Backend Engineer / Devops Engineer

招聘应聘danielglh 发表了文章 • 0 个评论 • 627 次浏览 • 2017-05-12 12:20 • 来自相关话题

Strikingly 是一个简单易用的建站平台,没有技术背景的用户也在很短的时间内创建和发布设计精美的网站。我们的产品自2012年8月发布以来增长迅速,第二个月就开始盈利... 查看全部

Strikingly 是一个简单易用的建站平台,没有技术背景的用户也在很短的时间内创建和发布设计精美的网站。我们的产品自2012年8月发布以来增长迅速,第二个月就开始盈利。创始团队于2013年初进入 Y Combinator 孵化项目,是 YC 毕业的第一个中国团队,获得了来自 SV Angel,Index Ventures, FundersClub,创新工场等机构的投资。目前 Strikingly 的用户遍布全球200多个国家和地区,提供6种语言的应用界面和客户支持。


2016年4月,我们正式推出了中国版产品 上线了sxl.cn,提供了更多符合本土国情和互联网生态的产品特性。



  • 我们的团队:一支诞生于硅谷,扎根在中国,快速成长的国际化创业团队

  • 我们的成员:一群执着于产品,以技术和设计为导向的年轻人

  • 我们期待的:志同道合,乐观向上,保持谦逊,不断突破,热爱创造价值的你



对我们技术团队正在干什么感兴趣的请看:Strikingly 团队2017技术展望


感兴趣的小伙伴们请发送简历至 jobs#strikingly.com 并注明来自 GoCN,也欢迎大家踊跃推荐,推荐成功有 1000 美金伯乐奖。


开放职位


Backend Engineer


职位描述



  • 负责后端系统架构的设计和实现

  • 负责后端服务性能的监控和优化

  • 负责后端服务的高可用性

  • 负责后端服务的安全性

  • 与其他团队成员紧密沟通合作,共同完成项目


职位要求



  • 熟练掌握以下主流编程语言中的一种或几种

    • Ruby

    • Go

    • Java

    • Node.js

    • C#

    • Python

    • Scala


  • 熟练掌握以上主流编程语言对应的主流 Web 框架

  • 掌握 Git 版本控制工具

  • 了解常见设计模式和编程最佳实践

  • 深刻理解 Web 应用相关的标准和最佳实践

  • 扎实的计算机科学基础知识,熟悉操作系统,数据库、常见数据结构和算法,以及软件设计实践

  • 熟悉 Linux / Unix 操作系统

  • 熟练的英语读写能力

  • 能迅速适应创业节奏和团队氛围


加分项



  • 熟悉 Ruby 和 Rails

  • 熟悉主流 Ruby Web 服务器的性能调优

  • Github 有后端项目超过 100 star,或给大型开源项目贡献过代码

  • 具备丰富的 Web 应用微服务架构实践经验

  • 具备丰富的 Web 应用高可用性实践经验

  • 具备丰富的 Web 应用性能优化实践经验

  • 具备丰富的 Web 应用安全实践经验

  • 优秀的英语交流能力


DevOps Engineer


职位描述



  • 负责系统和计算基础设施的搭建和维护

  • 负责系统和计算基础设施的监控、问题排查和故障处理

  • 负责设计、实现和优化内部容器平台

  • 负责设计、实现和优化内部部署工作流

  • 与其他技术团队成员紧密沟通合作,共同完成项目


职位要求



  • 熟悉 Linux / Unix 操作系统

  • 熟练掌握一门 Linux / Unix 环境下的通用编程语言

  • 掌握 Git 版本控制工具

  • 了解容器相关知识

  • 具备使用 Amazon Web Services / Google Cloud / Microsoft Azure 等云平台的经验

  • 具备使用 Terraform / Ansible / Chef / Puppet 等运维自动化工具的经验

  • 扎实的计算机科学基础知识,熟悉操作系统,数据库、常见数据结构和算法,以及软件设计实践

  • 熟练的英语读写能力

  • 快速学习成长,能迅速适应创业节奏和团队氛围


加分项



  • 熟练掌握 Go 编程语言

  • 具备丰富的 Amazon Web Services 实战经验

  • 精通 Docker 及其生态系统

  • 具备丰富的容器平台构建和维护经验

  • 熟练使用 Terraform

  • 熟练使用 Ansible

  • 设计并实现过开源的 DevOps 工具,或给大型开源项目贡献过代码

  • 优秀的代码设计能力

  • 优秀的英语交流能力


公司日常


每三个月一次脑洞大开的 Hackathon





参加各类技术大会




定期的技术分享




吃喝玩乐






感兴趣的小伙伴们请发送简历至 jobs#strikingly.com 并注明来自 GoCN,也欢迎大家踊跃推荐,推荐成功有 1000 美金伯乐奖。

发现一个有关error的非常奇怪的问题

有问必答winlin 回复了问题 • 5 人关注 • 5 个回复 • 183 次浏览 • 2017-05-12 10:31 • 来自相关话题

go调试的问题。

技术讨论winlin 回复了问题 • 5 人关注 • 5 个回复 • 191 次浏览 • 2017-05-12 10:20 • 来自相关话题

如何通过reflect为值为nil的指针创建实例

有问必答winlin 回复了问题 • 4 人关注 • 3 个回复 • 177 次浏览 • 2017-05-12 10:18 • 来自相关话题

GoCN每日新闻(2017-05-12)

回复

文章分享astaxie 发起了问题 • 3 人关注 • 0 个回复 • 264 次浏览 • 2017-05-12 10:09 • 来自相关话题

[北京]滴滴招聘golang工程师-业务系统

回复

招聘应聘Xargin 发起了问题 • 1 人关注 • 0 个回复 • 501 次浏览 • 2017-05-11 19:04 • 来自相关话题

GOLANG使用简单类型,在协议解析的妙用

技术讨论winlin 发表了文章 • 0 个评论 • 646 次浏览 • 2017-05-11 15:41 • 来自相关话题

在协议解析中,经常需要用到转换不同的含义,比如声音的采样率,在FLV中定义和AAC中定义是不同的。在FLV中只有4中采样率5512, 11025, 22050, 44100。而在AAC中有16种采样率96000, 8... 查看全部

在协议解析中,经常需要用到转换不同的含义,比如声音的采样率,在FLV中定义和AAC中定义是不同的。在FLV中只有4中采样率5512, 11025, 22050, 44100。而在AAC中有16种采样率96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350(还有4个是保留的)。也就是说,1在FLV中标识11025Hz,而在AAC中表示的是88200Hz。如何实现这个转换呢?


C++当然先得定义枚举:


enum SrsAudioSampleRate
{
SrsAudioSampleRate5512 = 0,
SrsAudioSampleRate11025,
SrsAudioSampleRate22050,
SrsAudioSampleRate44100,
SrsAudioSampleRateForbidden,
};

C++当然是用函数了:


SrsAudioSampleRate aac_to_flv(int v) {
if (v >= 0 && v <=5) {
return SrsAudioSampleRate44100;
} else if (v >=6 && v <= 8) {
return SrsAudioSampleRate22050;
} else if (v >= 9 && v <= 11) {
return SrsAudioSampleRate11025;
} else if (v == 12) {
return SrsAudioSampleRate5512;
} else {
return SrsAudioSampleRateForbidden;
}
}

看起来还是挺简单的。慢着,还有的时候需要打印出采样率来,所以还得搞个函数:


string srs_audio_sample_rate2str(SrsAudioSampleRate v)
{
switch (v) {
case SrsAudioSampleRate5512: return "5512";
case SrsAudioSampleRate11025: return "11025";
case SrsAudioSampleRate22050: return "22050";
case SrsAudioSampleRate44100: return "44100";
default: return "Forbidden";
}
}

拿到一个AAC的采样率,然后转换成FLV的,并打印出来,是这么使用的:


// 从文件或者流中读取出AAC的采样率的值。
int samplingFrequencyIndex = ...;
// 转换成FLV的采样率。
SrsAudioSampleRate sampleRate = aac_to_flv(samplingFrequencyIndex);
// 转换成字符串格式。
string sSampleRate = srs_audio_sample_rate2str(sampleRate);
// 打印采样率。
printf("SampleRate=%d/%sHz\n", sampleRate, sSampleRate);

有什么麻烦的呢?



  1. 函数和类型之间没有关系,每次使用的时候都得去翻手册啊翻手册。

  2. 如果定义成一个struct,那转换的时候又太麻烦了。


还能不能愉快的玩耍呢?用GOLANG吧!先看用法:


var sampleRate AudioSamplingRate
sampleRate.From(samplingFrequencyIndex)
fmt.Printf("SampleRate=%d/%v\n", sampleRate, sampleRate)

就是这么简单(此处应该有掌声)~


其实实现起来也非常自然:


type AudioSamplingRate uint8

const (
AudioSamplingRate5kHz AudioSamplingRate = iota // 0 = 5.5 kHz
AudioSamplingRate11kHz // 1 = 11 kHz
AudioSamplingRate22kHz // 2 = 22 kHz
AudioSamplingRate44kHz // 3 = 44 kHz
AudioSamplingRateForbidden
)

func (v AudioSamplingRate) String() string {
switch v {
case AudioSamplingRate5kHz:
return "5.5kHz"
case AudioSamplingRate11kHz:
return "11kHz"
case AudioSamplingRate22kHz:
return "22kHz"
case AudioSamplingRate44kHz:
return "44kHz"
default:
return "Forbidden"
}
}

func (v *AudioSamplingRate) From(a int) {
switch a {
case 0, 1, 2, 3, 4, 5:
*v = AudioSamplingRate44kHz
case 6, 7, 8:
*v = AudioSamplingRate22kHz
case 9, 10, 11:
*v = AudioSamplingRate11kHz
case 12:
*v = AudioSamplingRate5kHz
default:
*v = AudioSamplingRateForbidden
}
}


Remark: 代码参考go-oryx-lib flv.



有几个地方非常不同:



  1. 虽然GOLANG只是在uint8上面加了函数,但是使用起来方便很多了,以前在C++中用这两个枚举,每次都要跳到枚举的定义来看对应的函数是什么。

  2. GOLANG的switch比较强大,可以case好几个值,和C++的if有点想,但是GOLANG的case更直观,知道这几个值会被转换成另外的值,而if读起来像是将一个范围的值转换,不好懂。

  3. GOLANG的枚举使用const实现,也可以带类型,而且有个iota很强大,特别是在定义那些移位的枚举时就很好用。


好吧,这只是几个小的改进,虽然用起来很方便。来看看在AMF0中基本类型的妙用,AMF0是一种传输格式,和JSON很像,不过JSON是文本的,而AMF0是字节的,都是用来在网络中传输对象的。因此,AMF0定义了几个基本的类型:String, Number, Boolean, Object,其中Object的属性定义为String的属性名和值,值可以是其他的类型。


先看看C++的实现,首先定义一个AMF0Any对象,可以转换成具体的String或者Object等对象:


class SrsAmf0Any {
// 提供转换的函数,获取实际的值。
virtual std::string to_str();
virtual bool to_boolean();
virtual double to_number();
virtual SrsAmf0Object* to_object();
// 当然还得提供判断的函数,得知道是什么类型才能转。
virtual bool is_string();
virtual bool is_boolean();
virtual bool is_number();
virtual bool is_object();
// 提供创建基本类型的函数。
static SrsAmf0Any* str(const char* value = NULL);
static SrsAmf0Any* boolean(bool value = false);
static SrsAmf0Any* number(double value = 0.0);
static SrsAmf0Object* object();
};

在实现时,String和Number等基本类型可以隐藏起来(在cpp中实现):


namespace _srs_internal {
class SrsAmf0String : public SrsAmf0Any {
public:
std::string value;
// 当然它必须实现编码和解码的函数。
virtual int total_size();
virtual int read(SrsBuffer* stream);
virtual int write(SrsBuffer* stream);
};
}

AMF0Object当然得暴露出来的:


class SrsAmf0Object : public SrsAmf0Any {
public:
virtual int total_size();
virtual int read(SrsBuffer* stream);
virtual int write(SrsBuffer* stream);
// 提供设置和读取属性的方法。
virtual void set(std::string key, SrsAmf0Any* value);
virtual SrsAmf0Any* get_property(std::string name);
};

用起来是这样:


// 设置Object的属性,并发送给服务器。
SrsConnectAppPacket* pkt = NULL;
pkt->command_object->set("app", SrsAmf0Any::str(app.c_str()));
pkt->command_object->set("tcUrl", SrsAmf0Any::str(tcUrl.c_str()));

// 读取服务器的响应,取出服务器的IP等信息。
SrsConnectAppResPacket* pkt = NULL;
SrsAmf0Any* data = pkt->info->get_property("data");
if (si && data && data->is_object()) {
SrsAmf0Object* obj = data->to_objet();

SrsAmf0Any* prop = obj->get_property("srs_server_ip");
if (prop && prop->is_string()) {
printf("Server IP: %s\n", prop->to_str().c_str());
}

prop = obj->get_property("srs_pid");
if (prop && prop->is_number()) {
printf("Server PID: %d\n, prop->to_number());
}
}

看起来巨繁琐吧?快用GOLANG,如果换成GOLANG,可以用基本类型定义AMF0的基本类型,这样使用起来是这样:


pkt := or.NewConnectAppPacket()
pkt.CommandObject.Set("tcUrl", amf0.NewString(tcUrl))
pkt.CommandObject.Set("app", amf0.NewString(app))

var res *or.ConnectAppResPacket
if data, ok := res.Args.Get("data").(*amf0.Object); ok {
if data, ok := data.Get("srs_server_ip").(*amf0.String); ok {
fmt.Printf("Server IP: %s\n", string(*data))
}
if data, ok := data.Get("srs_pid").(*amf0.Number); ok {
fmt.Printf("Server PID: %d\n, int(*data))
}
}

区别在于:



  1. C++由于不能在基本类型上定义方法,导致必须创建struct或者class类型,有比较繁琐的类型转换和判断。

  2. GOLANG的类型判断,提供了ok的方式,一句话就能把类型转换弄好,而且接口和实现struct的对象可以重用变量名。

  3. 不必加很多类型判断,没有多余的变量,干净利索,需要维护的信息比较少。


实现起来更舒服,基本类型不用定义struct:


type String string
func (v *String) Size() int {}
func (v *String) UnmarshalBinary(data []byte) (err error) {}
func (v *String) MarshalBinary() (data []byte, err error) {}

type Object struct {}
func (v *Object) Size() int {}
func (v *Object) UnmarshalBinary(data []byte) (err error) {}
func (v *Object) MarshalBinary() (data []byte, err error) {}


Remark:代码参考go-oryx-lib amf0.



更神奇的是,因为Object、EcmaArray和StrictArray都是类似的结构,但是有些细微的差异,因此使用GOLANG的结构体嵌套可以很直接的解决问题:


type Object struct {
objectBase
eof objectEOF
}
type EcmaArray struct {
objectBase
count uint32
eof objectEOF
}
type StrictArray struct {
objectBase
count uint32
}

可以对比下SRS的实现,C++可以采用继承,而GOLANG直接组合那些基本的单元。


爱生活,爱够浪(此处可以响起掌声了)~