Redian新闻
>
分享:Go语言黑魔法(内存)
avatar
a*a
2
文章出处:安兰老师的占星城堡 / 伊莎贝
摩羯金星给人的印象,感觉大多是端庄、传统、高贵。自「卧虎藏龙」一炮而红的章子
怡,便是摩羯金星。2003年世界小姐季军的满族美女关琦,也正是摩羯金星。
摩羯金星的美,给人一种无法忽视的力量,在人群中,你很容易注意到他们。第一眼看
时,或许你并不觉得非常惊艳,但是,日子越久,越觉得美、更美。摩羯金星的魅力,
是一种耐人寻味的美感。
埃及裔的摩羯金星美女达丽妲Dalida,以她醇美无双的歌喉、高贵动人的容貌体态,一
度成为法国歌坛天后。她逝世之后,法国人精心为她立像,以纪念这位非凡的歌手。摩
羯金星的美,天长地久、永不凋凌。
摩羯金星适合穿较挺立,或是色彩素雅的服装。章子怡刚出道时,她私下的打扮仍偏向
其水瓶日座,现代感、多彩,和捧红她的「卧虎藏龙」中的扮相非常不同。在「卧虎藏
龙」中,她饰演一位满清贵族女孩,挺立的满清服装和发型,对摩羯金星来说再适合不
过了!满清服装让章子怡的摩羯金星魅力大发,让她一跃成为国际巨星。
许多摩羯金星朋友,满喜欢带有古意的服装。摩羯金星特别适合旗袍,或旗袍风的时尚
服装,旗袍似乎就是专门为摩羯金星设计的。即使是摩羯金星的西洋女孩,穿起来也格
外动人。
2003年世姐季军的关琦,刚好在决赛时有旗袍秀,不论哪一国小姐都穿上旗袍。身为满
族的她,又刚好是摩羯金星,将旗袍的端雅、高贵,又不失性感的女人味,都完美的表
现出来,不得奖是不可能的啊!
摩羯金星不但适合挺立、色彩较素雅的衣服,鞋子也是摩羯金星须要注意的部位,高雅
的高跟鞋、较细致的休闲鞋,都是很好的选择。千万别穿著球鞋啊!有一点跟的鞋子对
摩羯金星来说不错,因为摩羯金星也展现出一种「婷婷玉立」的美感。当然啦,如果不
是太正式的场合,还是穿平底鞋好好休息罗!
摩羯金星适合留长发或中长发,中性的短发不适合。想想如果章子怡剪了一头中性短发
,就觉得风格不对了!直发、大波浪卷都合适,或是梳发髻,也很能散发摩羯金星的高
贵之美。不论是何种发型,摩羯金星特别注意头发的整齐光鲜,一头散乱蓬松的头发,
就不大适合了。
妆容方面,摩羯金星可浓可淡。摩羯金星同时拥有素雅之美,也有深隧之美。平日妆扮
,可以选择颜色素雅、哑色的眼影,带闪光的不大合适。口红则以接近自然唇色为佳,
也以哑色为主。如果参加晚会,可以用眼线笔将眼睛圈起来,并使用浓密型的睫毛膏,
并最好画上唇线,让整个五官「立体分明」。不过,烟薰眼妆不适合摩羯金星喔!摩羯
金星即使化上浓妆,也力求乾净光鲜的感觉。
摩羯金星名人:
章子怡、2003世姐季军关琦、埃及歌手达丽妲Dalida、酒井法子、名模辛蒂克劳馥
Cindy Crawford、冰岛歌手碧玉Bjork、布兰妮Britney Spears、克拉克盖伯Clark
Gable、布莱德彼特Brad Pitt。
avatar
d*n
3
http://zhuanlan.zhihu.com/thought/20010926
达达 · 6 天前
今天我要教大家一些无用技能,也可以叫它奇技淫巧或者黑魔法。用得好可以提升性能
,用得不好就会招来恶魔,嘿嘿。
黑魔法导论
为了让大家在学习了基础黑魔法之后能有所悟,在必要的时候能创造出本文传授之外的
属于自己的魔法,这里需要先给大家打好基础。
学习Go语言黑魔法之前,需要先看清Go世界的本质,你才能获得像Neo一样的能力。
在Go语言中,Slice本质是什么呢?是一个reflect.SliceHeader结构体和这个结构体中
Data字段所指向的内存。String本质是什么呢?是一个reflect.StringHeader结构体和
这个结构体所指向的内存。
在Go语言中,指针的本质是什么呢?是unsafe.Pointer和uintptr。
当你清楚了它们的本质之后,你就可以随意的玩弄它们,嘿嘿嘿。
第一式 - 获得Slice和String的内存数据
让我小试身手,你有一个CGO接口要调用,需要你把一个字符串数据或者字节数组数据
从Go这边传递到C那边,比如像这个:mysql/conn.go at master · funny/mysql ·
GitHub
查了各种教程和文档,它们都告诉你要用C.GoString或C.GoBytes来转换数据。
但是,当你调用这两个函数的时候,发生了什么事情呢?这时候Go复制了一份数据,然
后再把新数据的地址传给C,因为Go不想冒任何风险。
你的C程序只是想一次性的用一下这些数据,也不得不做一次数据复制,这对于一个性
能癖来说是多麽可怕的一个事实!
这时候我们就需要一个黑魔法,来做到不拷贝数据又能把指针地址传递给C。
// returns &s[0], which is not allowed in go
func stringPointer(s string) unsafe.Pointer {
p := (*reflect.StringHeader)(unsafe.Pointer(&s))
return unsafe.Pointer(p.Data)
}
// returns &b[0], which is not allowed in go
func bytePointer(b []byte) unsafe.Pointer {
p := (*reflect.SliceHeader)(unsafe.Pointer(&b))
return unsafe.Pointer(p.Data)
}
以上就是黑魔法第一式,我们先去到Go字符串的指针,它本质上是一个*reflect.
StringHeader,但是Go告诉我们这是一个*string,我们告诉Go它同时也是一个unsafe.
Pointer,Go说好吧它是,于是你得到了unsafe.Pointer,接着你就躲过了Go的监视,
偷偷的把unsafe.Pointer转成了*reflect.StringHeader。
有了*reflect.StringHeader,你很快就取到了Data字段指向的内存地址,它就是Go保
护着不想给你看到的隐秘所在,你把这个地址偷偷告诉给了C,于是C就愉快的偷看了Go
的隐私。
第二式 - 把[]byte转成string
你肯定要笑,要把[]byte转成string还不简单?Go语言初学者都会的类型转换语法:[]
byte(str)。
但是你知道这么做的代价吗?既然我们能随意的玩弄SliceHeader和StringHeader,为
什么我们不能造个string给Go呢?Go的内部会不会就是这么做的呢?
先上个实验吧:
package labs28
import "testing"
import "unsafe"
func Test_ByteString(t *testing.T) {
var x = []byte("Hello World!")
var y = *(*string)(unsafe.Pointer(&x))
var z = string(x)
if y != z {
t.Fail()
}
}
func Benchmark_Normal(b *testing.B) {
var x = []byte("Hello World!")
for i := 0; i < b.N; i ++ {
_ = string(x)
}
}
func Benchmark_ByteString(b *testing.B) {
var x = []byte("Hello World!")
for i := 0; i < b.N; i ++ {
_ = *(*string)(unsafe.Pointer(&x))
}
}
这个实验先证明了我们可以用[]byte的数据造个string给Go。接着做了两组Benchmark
,分别测试了普通的类型转换和伪造string的效率。
结果如下:
$ go test -bench="."
PASS
Benchmark_Normal 20000000 63.4 ns/op
Benchmark_ByteString 2000000000 0.55 ns/op
ok github.com/idada/go-labs/labs28 2.486s
哟西,显然Go这次又为了稳定性做了些复制数据之类的事情了!这让性能癖怎么能忍受
avatar
O*e
4
顶一下
要开始穿高跟鞋了!!
avatar
J*G
5
我穿旗袍怎么看怎么土。。。
相关阅读
logo
联系我们隐私协议©2024 redian.news
Redian新闻
Redian.news刊载任何文章,不代表同意其说法或描述,仅为提供更多信息,也不构成任何建议。文章信息的合法性及真实性由其作者负责,与Redian.news及其运营公司无关。欢迎投稿,如发现稿件侵权,或作者不愿在本网发表文章,请版权拥有者通知本网处理。