StackExchange.Redis 之 hash 類型示例

来源:https://www.cnblogs.com/peterzhang123/archive/2020/02/16/12310384.html

StackExchange.Redis 的組件封裝示例網上有很多,自行百度搜索即可。 這裡只演示如何使用Hash類型操作數據: 1 // 在 hash 中存入或修改一個值 並設置order_hashkey有效期1分鐘,過期自動刪除;null為不過期 2 stopwatch.Start(); 3 va ...


StackExchange.Redis 的組件封裝示例網上有很多,自行百度搜索即可。

這裡只演示如何使用Hash類型操作數據:

1             // 在 hash 中存入或修改一個值  並設置order_hashkey有效期1分鐘,過期自動刪除;null為不過期
2             stopwatch.Start();
3             var isok = RedisCacheHelper.Instance.HashSet("order_hashkey", "order_hashfield", "10", TimeSpan.FromMinutes(1));
4             stopwatch.Stop();
5             Console.WriteLine("在hash中存入一個值消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());  

1             //判斷該欄位是否存在 hash 中
2             var isexists = RedisCacheHelper.Instance.HashExists("order_hashkey", "order_hashfield");
3             Console.WriteLine("判斷該欄位是否存在hash中:" + isexists);  //返回 True 或 False

             //從hash中移除指定欄位
             var isdel = RedisCacheHelper.Instance.HashDelete("order_hashkey", "order_hashfield");
             Console.WriteLine("從hash中移除指定欄位:" + isdel);  //返回 True 或 False
            //從hash中遞增  預設按1遞增
            var getincre = RedisCacheHelper.Instance.HashIncrement("order_hashkey", "order_hashfield");
            Console.WriteLine("從hash中遞增:" + getincre);  //返遞增後的值 11

            //從hash中遞減  預設按1遞減
            var getdecre = RedisCacheHelper.Instance.HashDecrement("order_hashkey", "order_hashfield");
            Console.WriteLine("從hash中遞減:" + getdecre);  //返遞減後的值  10

            //保存一個字元串類型集合
            string[] strarray = { "1", "2", "3", "4", "5" };
            RedisCacheHelper.Instance.HashSetList("orderlist_hashkey", strarray, m => { return "hashfield_" + m.ToString(); }, new TimeSpan(0, 0, 50));

            //從資料庫獲取10條數據
            stopwatch.Start();
            var getlist = TestRedis.GetOrderFormAll(10);
            stopwatch.Stop();
            Console.WriteLine("從資料庫獲取10條數據消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());

            //保存多個對象集合 非序列化
            stopwatch.Start();
            RedisCacheHelper.Instance.HashSetObjectList("objlist_hashkey", getlist, r => { return r.ordercode.ToString(); }, 1);
            stopwatch.Stop();
            Console.WriteLine("將10條數據存入HashRedis 消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());

 

            //保存或修改一個hash對象(序列化) 對key設置過期時間有時候起作用,有時候不起作用
            stopwatch.Start();
            RedisCacheHelper.Instance.HashSet<OrderForm>("orderform_hashkey", "orderform_hashfield", getlist.FirstOrDefault(), new TimeSpan(0, 0, 10), 2);
            stopwatch.Stop();
            Console.WriteLine("保存或修改一個hash對象(序列化)消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());


            //保存Hash對象集合 序列化   對key設置過期時間可以起作用
            stopwatch.Start();
            RedisCacheHelper.Instance.HashSet<OrderForm>("orderformlist_hashkey", getlist, m=> { return m.ordercode.ToString(); }, new TimeSpan(0, 0, 30), 3);
            stopwatch.Stop();
            Console.WriteLine("保存Hash對象集合(序列化)消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());

 

            //從Hash Redis獲取某一條訂單信息  反序列化
            stopwatch.Start();
            var getorderinfo = RedisCacheHelper.Instance.HashGet<OrderForm>("orderform_hashkey", "orderform_hashfield", 2);
            stopwatch.Stop();
            Console.WriteLine("從Hash Redis獲取某一條訂單信息消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());
            Console.WriteLine(getorderinfo.ordercode);
            Console.WriteLine(getorderinfo.Area);
            Console.WriteLine(getorderinfo.City);
            Console.WriteLine(getorderinfo.Province);
            Console.WriteLine(getorderinfo.PostTime);

            //根據hashkey 獲取所有的值  反序列化
            stopwatch.Start();
            var getorderlist = RedisCacheHelper.Instance.HashGetAll<OrderForm>("orderformlist_hashkey", 3);
            stopwatch.Stop();
            Console.WriteLine("根據hashkey 獲取所有的值消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());
            foreach (var item in getorderlist)
            {
                Console.WriteLine("獲取反序列化得到的ordercode: " + item.ordercode);
            }

            //根據hashkey獲取單個欄位hashField的值
            stopwatch.Start();
            var getvalue = RedisCacheHelper.Instance.HashGet("objlist_hashkey1", "City", 1);
            stopwatch.Stop();
            Console.WriteLine("獲取單個欄位hashField的值消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());
            Console.WriteLine("獲取City: " + getvalue);

            Console.WriteLine("------------------");
            Console.WriteLine();

            //獲取多個欄位hashField的值
            List<RedisValue> fieldlist = new List<RedisValue>() { "ordercode", "Province", "City", "Area" };
            stopwatch.Start();
            var getlist = RedisCacheHelper.Instance.HashGet("objlist_hashkey1", fieldlist.ToArray(), 1);
            stopwatch.Stop();
            Console.WriteLine("獲取多個欄位hashField的值消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());
            foreach (var item in getlist)
            {
                Console.WriteLine("獲取到的值: " + item);
            }

            //根據hashkey返回所有的HashFiled
            stopwatch.Start();
            var getkeylist = RedisCacheHelper.Instance.HashKeys("objlist_hashkey1", 1);
            stopwatch.Stop();
            Console.WriteLine("消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());
            foreach (var item in getkeylist)
            {
                Console.WriteLine("獲取到的HashFiled: " + item);
            }


            //根據hashkey返回所有HashFiled值
            stopwatch.Start();
            var getvaluelist = RedisCacheHelper.Instance.HashValues("objlist_hashkey1", 1);
            stopwatch.Stop();
            Console.WriteLine("消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());
            foreach (var item in getvaluelist)
            {
                Console.WriteLine("獲取到的HashFiled值: " + item);
            }

            //模擬併發場景 使用HashDecrement遞減功能  使用分散式鎖,但是線程線程排隊處理,有可能照成Redis超時
該示例會照成1個用戶搶多個
stopwatch.Start(); List<Task> taskList = new List<Task>(); for (int i = 1; i <= 100; i++) //模擬多個用戶同時請求 { var task = Task.Run(() => { try { //*************************開始**************** RedisValue token = Environment.MachineName; while (true) { if (RedisCacheHelper.Instance.LockAndDo("lock_key", token, () => { //在這裡處理併發邏輯 //先獲取庫存數 var getvalues = (int)RedisCacheHelper.Instance.HashGet("order_hashkey", "order_hashfield"); if (getvalues > 0) { //先自減,獲取自減後的值 int order_Num = (int)RedisCacheHelper.Instance.HashDecrement("order_hashkey", "order_hashfield", null); if (order_Num >= 0) { //下麵執行訂單邏輯(這裡不考慮業務出錯的情況) Console.WriteLine("我搶到了,還剩餘數量:" + order_Num); } else { Console.WriteLine("A商品已經被搶光了"); } return true; } else { Console.WriteLine("B商品已經被搶光了"); return true; } }, new TimeSpan(0, 0, 10))) { break; } } } catch (Exception ex) { Console.WriteLine(ex.Message); throw; } }); taskList.Add(task); } Task.WaitAll(taskList.ToArray()); stopwatch.Stop(); Console.WriteLine("模擬併發場景消耗時間:" + stopwatch.ElapsedMilliseconds.ToString());

搶購前庫存30個

 

 搶購後庫存0

 

這裡附上RedisHelp

        /// <summary>
        /// 判斷該欄位是否存在 hash 中
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public bool HashExists(string redisKey, string hashField, int db = -1)
        {
            try
            {
                _db = GetDatabase(db);
                return _db.HashExists(redisKey, hashField);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 從 hash 中移除指定欄位
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public bool HashDelete(string redisKey, string hashField, int db = -1)
        {
            try
            {
                _db = GetDatabase(db);
                return _db.HashDelete(redisKey, hashField);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 從 hash 中移除多個指定欄位
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public long HashDelete(string redisKey, IEnumerable<RedisValue> hashField, int db = -1)
        {
            try
            {
                _db = GetDatabase(db);
                return _db.HashDelete(redisKey, hashField.ToArray());
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 遞增  預設按1遞增  可用於計數
        /// </summary>
        /// <param name="key"></param>
        /// <param name="span"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public long HashIncrement(string redisKey, string hashField, TimeSpan? span = null, int db = -1)
        {
            try
            {
                _db = GetDatabase(db);
                var result = _db.HashIncrement(redisKey, hashField);
                //設置過期時間
                if (span != null)
                {
                    this.KeyExpire(redisKey, span);
                }
                return result;
            }
            catch (Exception)
            {

                throw;
            }
        }

        /// <summary>
        /// 遞減  預設按1遞減   可用於搶購類的案例
        /// </summary>
        /// <param name="key"></param>
        /// <param name="span"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public long HashDecrement(string redisKey, string hashField, TimeSpan? span = null, int db = -1)
        {
            try
            {
                _db = GetDatabase(db);
                var result = _db.HashDecrement(redisKey, hashField);
                //設置過期時間
                if (span != null)
                {
                    this.KeyExpire(redisKey, span);
                }
                return result;
            }
            catch (Exception)
            {
                throw;
            }
        }


        /// <summary>
        /// 在 hash 中保存或修改一個值   字元類型
        /// set or update the HashValue for string key 
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <param name="span">過期時間,可空</param>
        /// <returns></returns>
        public bool HashSet(string redisKey, string hashField, string value, TimeSpan? span = null, int db = -1)
        {
            try
            {
                _db = GetDatabase(db);
                if (span != null)
                {
                    //設置過期時間
                    this.KeyExpire(redisKey, span);
                }
                return _db.HashSet(redisKey, hashField, value);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 保存一個字元串類型集合  
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisKey">Redis Key</param>
        /// <param name="list">數據集合</param>
        /// <param name="getFiledKey">欄位key</param>
        public void HashSetList(string redisKey, IEnumerable<string> list, Func<string, string> getFiledKey, TimeSpan? span = null, int db = -1)
        {
            try
            {
                _db = GetDatabase(db);
                List<HashEntry> listHashEntry = new List<HashEntry>();
                foreach (var item in list)
                {
                    listHashEntry.Add(new HashEntry(getFiledKey(item), item));
                }
                _db.HashSet(redisKey, listHashEntry.ToArray());

                if (span != null)
                {
                    //設置過期時間
                    this.KeyExpire(redisKey, span);
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }


        /// <summary>
        /// 保存多個對象集合  非序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tableName">表名首碼</param>
        /// <param name="list">數據集合</param>
        /// <param name="getModelId">欄位key</param>
        public void HashSetObjectList<T>(string tableName, IEnumerable<T> list, Func<T, string> getModelId, int db = -1) where T : class
        {
            try
            {
                _db = GetDatabase(db);
                foreach (var item in list)
                {
                    List<HashEntry> listHashEntry = new List<HashEntry>();
                    Type t = item.GetType();//獲得該類的Type
                    foreach (PropertyInfo pi in t.GetProperties())
                    {
                        string name = pi.Name; //獲得屬性的名字,後面就可以根據名字判斷來進行些自己想要的操作
                        var value = pi.GetValue(item, null);  //用pi.GetValue獲得值
                        listHashEntry.Add(new HashEntry(name, value.ToString()));
                    }
                    _db.HashSet(tableName + getModelId(item), listHashEntry.ToArray());
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }


        /// <summary>
        /// 保存或修改一個hash對象(序列化)
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool HashSet<T>(string redisKey, string hashField, T value, TimeSpan? span = null, int db = -1) where T : class
        {
            try
            {
                _db = GetDatabase(db);
                var json = JsonConvert.SerializeObject(value);
                if (span != null)
                {
                    //設置過期時間
                    this.KeyExpire(redisKey, span);
                }
                return _db.HashSet(redisKey, hashField, json);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 保存Hash對象集合 序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisKey">Redis Key</param>
        /// <param name="list">數據集合</param>
        /// <param name="getModelId"></param>
        public void HashSet<T>(string redisKey, IEnumerable<T> list, Func<T, string> getModelId, TimeSpan? span = null, int db = -1) where T : class
        {
            try
            {
                _db = GetDatabase(db);
                List<HashEntry> listHashEntry = new List<HashEntry>();
                foreach (var item in list)
                {
                    string json = JsonConvert.SerializeObject(item);
                    listHashEntry.Add(new HashEntry(getModelId(item), json));
                }
                _db.HashSet(redisKey, listHashEntry.ToArray());

                if (span != null)
                {
                    //設置過期時間
                    this.KeyExpire(redisKey, span);
                }
            }
            catch (Exception ex)
            {
                throw;
            }
        }

        /// <summary>
        /// 從 hash 中獲取對象(反序列化)
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public T HashGet<T>(string redisKey, string hashField, int db = -1) where T : class
        {
            try
            {
                _db = GetDatabase(db);
                return JsonConvert.DeserializeObject<T>(_db.HashGet(redisKey, hashField));
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        ///  根據hashkey獲取所有的值  序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisKey"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public List<T> HashGetAll<T>(string redisKey, int db = -1) where T : class
        {
            List<T> result = new List<T>();
            try
            {
                _db = GetDatabase(db);
                HashEntry[] arr = _db.HashGetAll(redisKey);
                foreach (var item in arr)
                {
                    if (!item.Value.IsNullOrEmpty)
                    {
                        var t = JsonConvert.DeserializeObject<T>(item.Value);
                        if (t != null)
                        {
                            result.Add(t);
                        }
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return result;
        }


        /// <summary>
        ///  根據hashkey獲取所有的值  非序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="redisKey"></param>
        /// <param name="db"></param>
        /// <returns></returns>
        public IEnumerable<Dictionary<RedisValue, RedisValue>> HashGetAll(IEnumerable<string> redisKey, int db = -1)
        {
            List<Dictionary<RedisValue, RedisValue>> diclist = new List<Dictionary<RedisValue, RedisValue>>();
            try
            {
                _db = GetDatabase(db);
                foreach (var item in redisKey)
                {
                    HashEntry[] arr = _db.HashGetAll(item);
                    foreach (var he in arr)
                    {
                        Dictionary<RedisValue, RedisValue> dic = new Dictionary<RedisValue, RedisValue>();
                        if (!he.Value.IsNullOrEmpty)
                        {
                            dic.Add(he.Name, he.Value);
                        }
                        diclist.Add(dic);
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
            return diclist;
        }


        /// <summary>
        /// 根據hashkey獲取單個欄位hashField的值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public RedisValue HashGet(string redisKey, string hashField, int db = -1)
        {
            try
            {
                _db = GetDatabase(db);
                return _db.HashGet(redisKey, hashField);
            }
            catch (Exception)
            {
                throw;
            }
        }

        /// <summary>
        /// 根據hashkey獲取多個欄位hashField的值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        public RedisValue[] HashGet(string redisKey, RedisValue[] hashField, int db = -1)
        {
            _db = GetDatabase(db);
            return _db.HashGet(redisKey, hashField);
        }

        /// <summary>
        /// 根據hashkey返回所有的HashFiled
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public IEnumerable<RedisValue> HashKeys(string redisKey, int db = -1)
        {
            _db = GetDatabase(db);
            return _db.HashKeys(redisKey);
        }

        /// <summary>
        /// 根據hashkey返回所有HashValue值
        /// </summary>
        /// <param name="redisKey"></param>
        /// <returns></returns>
        public RedisValue[] HashValues(string redisKey, int db = -1)
        {
            _db = GetDatabase(db);
            return _db.HashValues(redisKey);
        }
View Code

您的分享是我們最大的動力!

更多相關文章
  • 在Kubernetes中,通常kube schduler和kube controller manager都是多副本進行部署的來保證高可用,而真正在工作的實例其實只有一個。這裡就利用到 的選主機制,保證leader是處於工作狀態,並且在leader掛掉之後,從其他節點選取新的leader保證組件正常工 ...
  • 前言 這兩天一番花兩天的時間,重新用python和python圖形化開發工具tkinter,完善了下PDF合併小工具,終於可以發佈了。 工具目前基本功能已經完善,後期如果有反饋可以修複部分bug或完善需求。 這個工具基本具備了一個面向大眾的特性,只要是windows用戶,都可以很容易使用。 PDF合 ...
  • 題目:將你的 QQ 頭像(或者微博頭像)右上角加上紅色的數字,類似於微信未讀信息數量那種提示效果。 類似於圖中效果: 代碼: 效果如下: 原圖: 輸出: 附一個Pillow庫的文檔:https://pillow.readthedocs.io/en/3.1.x/index.html ...
  • 前言 因為昨天重新研究了下python的打包方法,今天一番準備把之前寫的一個pdf合併軟體重新整理一下,打包出來。 但在打包的過程中仍然遇到了一些問題,半年前一番做打包的時候也遇到了一些問題,現在來看,解決這些問題思路清晰多了,這裡記錄下。 問題 打包成功,但運行時提示Failed to execu ...
  • 話不多說直接上代碼: // set添加單個元素 stopwatch.Start(); var isok = RedisCacheHelper.Instance.SetAdd("setkey", "10"); stopwatch.Stop(); Console.WriteLine("set添加單個元素 ...
  • 前面四章介紹了繼承自Shape的類,包括Rectangle、Ellipse、Polygon以及Polyline。但還有一個繼承自Shape的類尚未介紹,而且該類是到現在為止功能最強大的形狀類,即Path類。Path類能夠包含任何簡單形狀、多組形狀以及更複雜的要素,如曲線。 Path類提供了Data屬 ...
  • " 返回《C 併發編程》" "1. 簡介" "2. 非同步下的共用變數" "3. 解析 AsyncLocal" "3.1. IAsyncLocalValueMap 的實現" "3.2. 結論" 1. 簡介 + 普通 共用變數: + 在某個類上用靜態屬性的方式即可。 + 多線程 共用變數 + 希望能將這 ...
  • using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace 回調函數Demo { /* 回調函數的作用,1.分裝;2.非同步;3.擴展具體方法。 * 通過一個委托給出實現 ...
一周排行
  • 《ASP.NET MVC 企業級實戰》 [作者] (中) 鄒瓊俊[出版] 清華大學出版社[版次] 2017年04月 第1版[印次] 2019年08月 第6次 印刷[定價] 89.00元 【第01章】 (P021) 只有在 Lambda 有一個輸入參數時,括弧才是可選的,否則括弧是必需的。 使用空括弧 ...
  • 上一篇(https://www.cnblogs.com/meowv/p/12971041.html)使用HtmlAgilityPack抓取壁紙數據成功將圖片存入資料庫,本篇繼續來完成一個全網各大平臺的熱點新聞數據的抓取。 同樣的,可以先預覽一下我個人博客中的成品:https://meowv.com/ ...
  • 前言 請了一天假後回公司,同事跟我說使用Newtonsoft.json序列化TreeView對象的時候出現報錯; 啊!什麼?這個類庫不是能夠序列化所有東西嗎?真的很懵逼,也是我第一次使用這個類庫出現問題! 問題異常 異常信息 : Newtonsoft.Json.JsonSerializationEx ...
  • 簡單瞭解下麵詞語的意思 節點:二叉樹中每個元素都稱為節點 葉子節點(簡稱:葉子):度為0的節點,葉子節點就是樹中最底段的節點,葉子節點沒有子節點,也叫終端結點 分枝節點:度不為0的結點 節點的度:二叉樹的度代表某個節點的孩子或者說直接後繼的個數,簡單說就是一個節點擁有的子樹數 樹的度: 樹中最大的結 ...
  • C# 中的LINQ 提供了兩種操作方式,查詢表達式和查詢操作符,所有的查詢表達式都有對應的查操作符類替代,查詢表達式有點“類” SQL,在代碼中寫SQL,總覺得不夠“優雅”,使用查詢操作符就顯得“優雅”很多, 本系列就來對所有的LINQ 標準操作符進行一個全面的總結,這些操作符和我上篇文章總結的Rx ...
  • 在Startup ConfigureServices 註冊本地化所需要的服務AddLocalization和 Configure<RequestLocalizationOptions> public void ConfigureServices(IServiceCollection services ...
  • 為什麼需要持久化,以及Redis持久化的RDB方式在這篇文章講的已經很透徹了,足以弔打面試官了。而且此篇內容需要RDB文章的內容支持,所以建議先看下:看完這篇還不懂Redis的RDB持久化,你們來打我! 一、什麼是AOF 它也是Redis持久化的重要手段之一,aof->Append Only Fil ...
  • 先上圖: @IT程式猿 微博網友評論: @迢書:前同事的,親眼見過 @AvenGeeker:Bug 404 @科技州:這是要逼死強迫症 @小島一瞥:哈哈哈哈哈我老家的車 最後小編整理了一套技術資料不僅能精準消除技術盲點、累計面試經驗,更可以攻剋JVM、Spring、分散式、微服務等技術難題。 海量電 ...
  • 概括來說,分三步: 1,首先找到是哪個進程的CPU占有率飆到了100%。 2,根據進程號pid,定位到是哪個線程,找到對應線程的tid。 3,導出對應線程的dump日誌文件,分析日誌文件定位具體代碼。 要解決這個問題,你應該具備以下技能: 1,linux的top命令。 2,jvm監控工具jps。 3 ...
  • 寫在最後 程式員為何害怕【別人的代碼】呢?這讓我想起一個段子。 寫這段代碼時 只有上帝和我知道他是幹嘛的 現在 只有上帝知道了 別人的代碼,似乎總意味著冗長、晦澀、凌亂,給人一種不想靠近的感覺。搞笑的是,對於一些程式員而言,即使是自己的代碼,在一段時間之後自己再拿來看,也成了【別人的代碼】... 作 ...