Copy a hash.Hash

agolangf · · 772 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>To calculate the hashes of &#39;hello space&#39; and &#39;hello world&#39; without processing &#39;hello &#39; twice, in python I write:</p> <pre><code>&gt;&gt;&gt; a = hashlib.sha1() &gt;&gt;&gt; a.update(&#39;hello &#39;) &gt;&gt;&gt; b = a.copy() &gt;&gt;&gt; a.update(&#39;space&#39;) &gt;&gt;&gt; b.update(&#39;world&#39;) &gt;&gt;&gt; a.hexdigest(), b.hexdigest() (&#39;0db22b798fcb792be5fed7ef8c105cc1ed75f540&#39;, &#39;2aae6c35c94fcfb415dbe95f408b9ce91ee846ed&#39;) </code></pre> <p>(yes, I understand about block sizes; assume &#39;hello &#39; is many, many blocks in length.)</p> <p>My attempt at a golang-equivalent:</p> <pre><code>var a = sha1.New() a.Write([]byte(&#34;hello &#34;)) var b = a // want a deep copy here a.Write([]byte(&#34;space&#34;)) b.Write([]byte(&#34;world&#34;)) var ha = a.Sum(nil) var hb = b.Sum(nil) fmt.Println(hex.EncodeToString(ha)) fmt.Println(hex.EncodeToString(hb)) </code></pre> <p>So: how do I deep-copy a hash.Hash?</p> <p>edit: reword problem; I want to calculate lots of different hashes with the same prefix.</p> <hr/>**评论:**<br/><br/>dgryski: <pre><p>No way to do it in general. Probably something hacky with unsafe and reflection. However for sha1, <a href="https://github.com/TvdW/gotor/tree/master/sha1">https://github.com/TvdW/gotor/tree/master/sha1</a></p></pre>tv64738: <pre><p>You can&#39;t just deep-copy arbitrary things and expect them to work right. Making a copy is not part of the hash.Hash interface, and not all hash functions expose a mechanism to copy the internal state.</p></pre>TheMerovius: <pre><p>My best answer would be: <a href="http://play.golang.org/p/zfrGu4mrIU" rel="nofollow">http://play.golang.org/p/zfrGu4mrIU</a></p> <p>[edit] hm, that doesn&#39;t really address the issue. So no, I don&#39;t think that&#39;s possible at all in go currently.</p></pre>bradfitz: <pre><p>This isn&#39;t possible with the standard library. </p></pre>gohacker: <pre><p>O RLY?</p> <pre><code>func copyHash(src hash.Hash) hash.Hash { typ := reflect.TypeOf(src) val := reflect.ValueOf(src) if typ.Kind() == reflect.Ptr { typ = typ.Elem() val = val.Elem() } elem := reflect.New(typ).Elem() elem.Set(val) return elem.Addr().Interface().(hash.Hash) } </code></pre></pre>bradfitz: <pre><p>My answer was short for:</p> <p>This isn&#39;t possible with the standard library in a way that is supported, easy, clear, and non-disgusting. :)</p></pre>szabba: <pre><p>At least they wrapped it with a sensibly-typed funcion. ;)</p></pre>dgryski: <pre><p>Yoinked for later </p></pre>gsscoder: <pre><p>May this package can help you: <a href="https://godoc.org/code.google.com/p/rog-go/exp/deepcopy" rel="nofollow">https://godoc.org/code.google.com/p/rog-go/exp/deepcopy</a> ?</p></pre>stevvooe: <pre><p>We created a <a href="http://godoc.org/github.com/stevvooe/resumable" rel="nofollow">resumable hash package</a> for doing this type of operation. Just side-effect import the resumable version of the package and instantiate through standard <code>crypto.SHA256.New()</code>. That instance will be a <code>hash.Hash</code> and can be used as such anywhere. When you need to save the state, just type assert to <code>resumable.Hash</code> and use <code>(resumable.Hash).Save</code> and <code>(resumable.Hash).Restore</code> to accomplish your goal.</p> <p>Note this is more for state serialization rather than deep copy. We could add that, if desired, since deep copy is a very similar operation.</p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

772 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传