<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[phpduang的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/phpduang</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; phpduang]]></copyright><item><title><![CDATA[单链表反转-golang实现]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/114334647</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/114334647</guid><author>phpduang</author><pubDate>Wed, 03 Mar 2021 20:52:55 +0800</pubDate><description><![CDATA[package main

import (
	"fmt"
)
// 链表节点
type Node struct {
	value int
	next *Node
}
// 链表
type Link struct {
	head *Node
	size int
}
func main() {
	n1:=&amp;Node{value: 1}
	n2:=&amp;Node{next: n1,value: 2}
	n3:=&amp;Node{next: n2,value: 3}
	n4:=&amp;Node{.]]></description><category></category></item><item><title><![CDATA[go slice 第三个参数是容量]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/114004891</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/114004891</guid><author>phpduang</author><pubDate>Tue, 23 Feb 2021 22:47:11 +0800</pubDate><description><![CDATA[go slice 切片包括左边不包括右边，左包右不包这个例子中 ，

2~6 长度len为4,

2~7 容量cap为5






	s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	
	
	s1 := s[2:5] // [2 3 4]
	
	
	s2 := s1[2:6:7] // [4 5 6 7]
	
	
	
	fmt.Println(s1, s2, len(s2), cap(s2))
	
	
	//[2 3 4] [4 5 6 7] 4 5
	
	
...]]></description><category></category></item><item><title><![CDATA[Golang的反射reflect深入理解和示例]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/113316215</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/113316215</guid><author>phpduang</author><pubDate>Thu, 28 Jan 2021 11:23:20 +0800</pubDate><description><![CDATA[编程语言中反射的概念

在计算机科学领域，反射是指一类应用，它们能够自描述和自控制。也就是说，这类应用通过采用某种机制来实现对自己行为的描述（self-representation）和监测（examination），并能根据自身行为的状态和结果，调整或修改应用所描述行为的状态和相关的语义。

每种语言的反射模型都不同，并且有些语言根本不支持反射。Golang语言实现了反射，反射机制就是在运行时动态的调用对象的方法和属性，官方自带的reflect包就是反射相关的，只要包含这个包就可以使用。

多插一句，Gol]]></description><category></category></item><item><title><![CDATA[golang 快速排序-递归]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/112727446</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/112727446</guid><author>phpduang</author><pubDate>Sun, 17 Jan 2021 00:44:12 +0800</pubDate><description><![CDATA[package main

import (
	"fmt"
	"math"
)

/**
 * 递归三要素
 * 1.找到递归终止时机-》切片长度为1时候
 * 2.将问题分解成小粒度（需要满足小粒度的解法和原来一样）-》找一个中间值，然后分成左、右两部分 去分别求解
 * 3.明白在单个粒度中需要做什么-》先左、右分布求解，然后合并结果
 */
func qs(a []int64) []int64 {
	length := len(a)
	//尽头条件(停止递归的时机)
	if length &lt;=.]]></description><category></category></item><item><title><![CDATA[二叉搜索树 -golang实现]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/112726511</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/112726511</guid><author>phpduang</author><pubDate>Sat, 16 Jan 2021 22:55:10 +0800</pubDate><description><![CDATA[package main

import (
	"fmt"
	"math"
)

// 二叉树的数据结构
type TreeNode struct {
	Data  int
	Left  *TreeNode
	Right *TreeNode
}

// 新增节点
func (node *TreeNode) Add(v int) {
	//根节点
	if node.Data == math.MinInt64 {
		node.Data = v
		return
	}
	if v &lt; node.Data.]]></description><category></category></item><item><title><![CDATA[golang -三数之和为0]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/112445724</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/112445724</guid><author>phpduang</author><pubDate>Sun, 10 Jan 2021 21:47:48 +0800</pubDate><description><![CDATA[package main

import (
	//	"fmt"
	"fmt"
	"sort"
)

func main() {
	nums := []int{-1, -1, 2, 0, -2, -2, 4}
	fmt.Println(threeSum(nums))
}

func threeSum(nums []int) [][]int {
	// 先从小到大排序
	sort.Ints(nums)
	// 接收结果
	var res [][]int
	// 获取数组长度
	length := len(n.]]></description><category></category></item><item><title><![CDATA[golang skiplist(跳表)实现]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/111087211</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/111087211</guid><author>phpduang</author><pubDate>Sat, 12 Dec 2020 23:58:17 +0800</pubDate><description><![CDATA[前言

首先来了解一下跳表的概念，跳表中的表指的是链表，所以宏观上来看跳表是一种链表结构，那么它与传统的链表有什么不同呢？一般的单链表如果我们需要查找第n个元素，那么就需要从头节点开始一个一个的遍历n次，时间复杂读就是O(n)，而跳表就是在单链表之上做了一些优化，使时间复杂度达到O(logn)。

在O(logn)复杂度内查找元素，我们不难想到其他的数据结构，avl树，红黑树，b树，b+树之类。但是这些树状结构有个共性就是需要在元素数量发生变化的时候保持平衡才能继续维持性能，所以就需要做一个额外的操作，旋转]]></description><category></category></item><item><title><![CDATA[彻底弄明白mysql的B+树索引]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/109935124</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/109935124</guid><author>phpduang</author><pubDate>Sun, 22 Nov 2020 12:28:01 +0800</pubDate><description><![CDATA[正确的创建合适的索引，是提升数据库查询性能的基础。在正式讲解之前，对后面举例中使用的表结构先简单看一下：


create table user
(
    id     bigint  not null comment 'id' primary key,
    name   varchar(200) null comment 'name',
    age    bigint       null comment 'age',
    gender int          null comment ']]></description><category></category></item><item><title><![CDATA[图解Golang的channel底层原理]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/109278030</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/109278030</guid><author>phpduang</author><pubDate>Sun, 25 Oct 2020 20:09:57 +0800</pubDate><description><![CDATA[此文章转自互联网技术窝

废话不多说，直奔主题。

channel的整体结构图



简单说明：

buf是有缓冲的channel所特有的结构，用来存储缓存数据。是个循环链表
	sendx和recvx用于记录buf这个循环链表中的~发送或者接收的~index
	lock是个互斥锁。
	recvq和sendq分别是接收(&lt;-channel)或者发送(channel &lt;- xxx)的goroutine抽象出来的结构体(sudog)的队列。是个双向链表
源码位于/runtime/chan.go中(目前]]></description><category></category></item><item><title><![CDATA[Go slice详解]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/109276377</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/109276377</guid><author>phpduang</author><pubDate>Sun, 25 Oct 2020 17:39:36 +0800</pubDate><description><![CDATA[slice表示切片(分片)，例如对一个数组进行切片，取出数组中的一部分值。在现代编程语言中，slice(切片)几乎成为一种必备特性，它可以从一个数组(列表)中取出任意长度的子数组(列表)，为操作数据结构带来非常大的便利性，如python、perl等都支持对数组的slice操作，甚至perl还支持对hash数据结构的slice。

但Go中的slice和这些语言的slice不太一样，前面所说的语言中，slice是一种切片的操作，切片后返回一个新的数据对象。而Go中的slice不仅仅是一种切片动作，还是一种数据]]></description><category></category></item><item><title><![CDATA[golang context的具体使用场景举例-rpc并发调用]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/108684785</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/108684785</guid><author>phpduang</author><pubDate>Sat, 19 Sep 2020 19:15:31 +0800</pubDate><description><![CDATA[rpc调用是在实际开发场景中经常用到的，假设某个用户请求的处理需要3个RPC并行请求，设置一个整体任务的超时时间，如果到达超时时间后，不管RPC有没有执行完毕任务都返回，实现逻辑见下面代码：


package main

import (
	"context"
	"fmt"
	"strconv"
	"sync"
	"time"
)

//rpc调用
func Rpc(ctx context.Context, url string) string {
	result := make(chan string)]]></description><category></category></item><item><title><![CDATA[golang的路由数据结构-基数树radix]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/108516475</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/108516475</guid><author>phpduang</author><pubDate>Thu, 10 Sep 2020 16:02:08 +0800</pubDate><description><![CDATA[Radix树

Radix树，即基数树，也称压缩前缀树，是一种提供key-value存储查找的数据结构。与Trie不同的是，它对Trie树进行了空间优化，只有一个子节点的中间节点将被压缩。同样的，Radix树的插入、查询、删除操作的时间复杂度都为O(k)。

Radix树特点

一般由根节点、中间节点和叶子节点组成。
	每个节点可以包含一个或多个字符。
	树的叶子结点数即是数据条目数。
	从根节点到某一节点经过路径的字符连起来即为该节点对应的字符串。
	每个节点的所有子节点字符串都不相同。
插入操作

对r]]></description><category></category></item><item><title><![CDATA[golang 实现双向链表]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/108309498</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/108309498</guid><author>phpduang</author><pubDate>Sun, 30 Aug 2020 18:49:34 +0800</pubDate><description><![CDATA[package main

//链表节点
type doublLinkeNode struct {
	data interface{}     //节点存在的数据
	pre  *doublLinkeNode //指向上一个节点的指针
	next *doublLinkeNode //指向下一个节点的指针
}

//链表数据结构（两个指针 一个指向头节点、一个指向尾节点 便于可以从两边获取数据）
type doubleLink struct {
	head   *doublLinkeNode //指向头结点
.]]></description><category></category></item><item><title><![CDATA[hashmap的golang实现]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/108300932</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/108300932</guid><author>phpduang</author><pubDate>Sat, 29 Aug 2020 23:08:01 +0800</pubDate><description><![CDATA[/**
*
* hashMap的golang实现
*
**/

package main

//桶的格子数
const BucketsCount = 20

//node节点
type Node struct {
	Next *Node
	Data Value
}

//node节点存放的实际对象
type Value struct {
	Key   string
	Value interface{}
}

//hashMap 桶
type HashMap struct {
	Buckets [Bu...]]></description><category></category></item><item><title><![CDATA[CIDR地址块及其子网划分（内含原始IP地址分类及其子网划分的介绍）]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/108028847</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/108028847</guid><author>phpduang</author><pubDate>Sat, 15 Aug 2020 21:47:50 +0800</pubDate><description><![CDATA[CIDR地址块及其子网划分（内含原始IP地址分类及其子网划分的介绍）



1. 原始的IP地址表示方法及其分类（近几年慢慢淘汰）



  IP地址是由4字节，32位表示的，为了表示方便，通常用点分十进制表示法，例如大家常见的：192.168.0.52，四个字节，通过点进行分隔，看起来十分清晰。IP地址的32位是由网络号+主机号组成的，也就是说这32位中，左边的某些连续位表示网络号，右边的某些连续位表示主机号，那么我们平常在讨论这一系列问题的时候，会有一个“网络地址”的概念，一般来说网络地址并不等...]]></description><category></category></item><item><title><![CDATA[谈谈NAT：什么？全球IP和私有IP是什么鬼？]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/108000011</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/108000011</guid><author>phpduang</author><pubDate>Fri, 14 Aug 2020 10:54:10 +0800</pubDate><description><![CDATA[可能你们会经常听到全球 IP(外网)和私有 IP(内网)，他们的区别是什么呢？今天这篇文章来简单讲讲这到底是怎么回事。

我们都知道，IPv4中的IP地址的数量是有限的，每次把一部分地址分配出去，那么就意味着能够用来分配的IP地址就更少了，而且随着现在手机，电脑等的快速发展，如果每个手机或者电脑都要求一个IP地址，那么显然IP地址是不够用的。

为了解决这个问题，我们可以采取这样的策略：例如对于一个公司来说，每个公司都会有一个属于自己公司的内网(也可以称之为局域网)。

假如我们给这个公司A分配了一个IP=]]></description><category></category></item><item><title><![CDATA[golang recover异常捕获容易踩的坑]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/107989304</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/107989304</guid><author>phpduang</author><pubDate>Thu, 13 Aug 2020 19:26:27 +0800</pubDate><description><![CDATA[1.error

Golang被诟病非常多的一点就是缺少强大方便的异常处理机制，大部分高级编程语言，比如Java、PHP、Python等都拥有一种try catch机制，这种异常捕获机制可以非常方便的处理程序运行中可能出现的各种意外情况。

严格来说，在Go里面，错误和异常是2种不同的类型，错误一般是指程序产生的逻辑错误，或者意料之中的意外情况，而且异常一般就是panic，比如角标越界、段错误。

对于错误，Golang采用了一种非常原始的手段，我们必须手动处理可能产生的每一个错误，一般会把错误返回给调用方]]></description><category></category></item><item><title><![CDATA[golang全局变量的坑-尽量别用全局变量]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/107943247</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/107943247</guid><author>phpduang</author><pubDate>Tue, 11 Aug 2020 19:55:31 +0800</pubDate><description><![CDATA[]]></description><category></category></item><item><title><![CDATA[BT种子的技术原理是什么？就是.torrent文件该如何理解？]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/107931030</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/107931030</guid><author>phpduang</author><pubDate>Tue, 11 Aug 2020 11:10:20 +0800</pubDate><description><![CDATA[看到很多咨询BT种子原理的问题，在这里整理些资料，希望对需要的朋友有帮助。



可以分两个层面来分析一下：

1、torrent文件的原理：如果这个问题是指torrent文件本身，那么，当你对一个文件（或者文件夹）制作成.torrent文件，实际上生成的.torrent文件里面主要包括了这些信息：

 A）这个文件（文件夹）中数据的SHA1值，比如一个1G的文件，如果按1M每块进行分块，则会被分为了1000块，torrent中就会有这1000个数据块的指纹值（SHA1的hash值），这个占据了to...]]></description><category></category></item><item><title><![CDATA[如何理解虚拟内存]]></title><link>https://blog.youkuaiyun.com/phpduang/article/details/107898745</link><guid>https://blog.youkuaiyun.com/phpduang/article/details/107898745</guid><author>phpduang</author><pubDate>Sun, 09 Aug 2020 19:40:01 +0800</pubDate><description><![CDATA[为什么不直接使用物理内存

虚拟内存是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存（一个连续完整的地址空间），而实际上，它通常是被分隔成多个物理内存碎片，还有部分暂时存储在外部磁盘存储器上，在需要时进行数据交换。
现代所有用于一般应用的操作系统都对普通的应用程序使用虚拟内存技术，老一些的操作系统，如DOS和1980年代的Windows，或者那些1960年代的大型机，一般都没有虚拟内存的功能
——维基百科

读完上面的信息，我们可以得知，虚拟内存这个概念是后来才提出的，一开始并没...]]></description><category></category></item></channel></rss>