go语言基础--面向对象杂谈

news2024/11/15 5:20:58

面向过程

所谓的面向过程就是:强调的是步骤、过程、每一步都是自己亲自去实现的。

面向对象

所谓的面向对象其实就是找一个专门做这个事的人来做,不用关心具体怎么实现的。
所以说,面向过程强调的是过程,步骤。而面向对象强调的是对象,也就是干事的人。
在程序中,可以通过属性和方法(函数)来描述类。属性就是特征,方法(函数)就是行为。

面向对象编程好处

封装
继承
多态

继承

继承是一种类间关系,描述一个类从另一个类获取成员信息的类间关系。
继承必定发生在两个类之间,参与继承关系的双方称为父类和子类。
父类提供成员信息,子类获取成员信息。
通过匿名字段来实现继承
在这里插入图片描述

package main

import "fmt"

type Student struct {
	//属性---成员
	//方法---函数
	Person //匿名字段,只有类型,没有成员的名字

	score float64
}

type Teacher struct {
	Person //匿名字段,只有类型,没有成员的名字
	salary float64
}

type Person struct {
	id   int
	name string
	age  int
}

func main() {
	var stu Student = Student{Person{1, "张三", 18}, 98}
	fmt.Println(stu) //{{1 张三 18} 98}

	//部分初始化
	var stu1 Student = Student{score: 90}
	fmt.Println(stu1) //{{0  0} 90}

	var stu2 Student = Student{Person: Person{id: 101}} //{{101  0} 0}
	fmt.Println(stu2)
}

成员操作

package main

import "fmt"

type Student struct {
	//属性---成员
	//方法---函数
	Person //匿名字段,只有类型,没有成员的名字

	score float64
}

type Person struct {
	id   int
	name string
	age  int
}

func main() {
	var stu Student = Student{Person{101, "张三", 18}, 98}
	var stu1 Student = Student{Person{102, "李四", 18}, 80}

	//获取成员的值
	fmt.Println(stu.score)      //98
	fmt.Println(stu1.score)     //80
	fmt.Println(stu1.Person.id) //102 //比较麻烦
	fmt.Println(stu1.id)        //102

	//修改成员的值
	stu.score = 100
	fmt.Println(stu.score) //100

}

指针类型匿名字段

package main

import "fmt"

type Student struct {
	//属性---成员
	//方法---函数
	*Person //指针类型匿名字段

	score float64
}

type Person struct {
	id   int
	name string
	age  int
}

func main() {
	var stu Student = Student{&Person{101, "张三", 18}, 98}
	fmt.Println(stu)      //{0xc000054460 98} 父类输出的是结构体内存地址 只能使用成员操作了
	fmt.Println(stu.name) //张三
}

多重继承—尽量不要写多重继承

package main

import "fmt"

// Student 学生继承person
type Student struct {
	//属性---成员
	//方法---函数
	Person //指针类型匿名字段

	score float64
}

// Person 父类 person继承object
type Person struct {
	Object1
	name string
	age  int
}

type Object1 struct {
	id int
}

func main() {

	var stu Student
	stu.age = 18
	fmt.Println(stu.Person.age) //18
	stu.id = 101
	fmt.Println(stu.Person.Object1.id)
}

为结构体添加方法—封装

func  (对象 结构体类型) 方法名 (参数列表)(返回值列表) {
	
		代码体

}

方法调用

对象名.方法

//不支持重载,只要接收者类型不一样,这个方法就算同名,也是不同方法,不会出现重复定义函数的错误

package main

import "fmt"

// Student
type Student struct {
	id   int
	name string
	age  int
}

// PrintShow 方法 s为接收者
func (s Student) PrintShow() {
	fmt.Println(s) //{101 ziye 18}
}

func (s Student) EditInfo() {
	s.age = 20
}

func (s *Student) EditInfo1() {
	s.age = 20
}
func main() {
	stu := Student{101, "ziye", 18}
	//对象名.方法名 把stu中的值传给了s
	stu.PrintShow() //完成对方法的调用
	stu.EditInfo()  //不是引用传递,是值传递
	stu.PrintShow()
	//内部会进行转换
	stu.EditInfo1() //引用传递
	stu.PrintShow() //{101 ziye 20}
}

注意事项

只要接收者类型不一样,这个方法就算同名,也是不同方法
接收者为指针类型

package main

import "fmt"

// Student
type Student struct {
	id   int
	name string
	age  int
}

type Teacher struct {
	id   int
	name string
}

func (s *Student) show() {
	fmt.Println(s)
}

func (t *Teacher) show() { //把teacher内存地址给到这里
	fmt.Println(t)
}
func main() {
	//如果接收者类型不同,即使方法的名字是相同的也是不同的方法
	stu := Student{101, "ziye", 18}
	stu.show() //等价于(&stu).show()
	teacher := Teacher{102, "ziyeye"}
	teacher.show()
}

面向对象方法练习

定义一个学生类,有六个属性,分别为姓名、性别、年龄、语文、数学、英语成绩
定义两个方法:

第一方法:打招呼的方法:介绍自己叫XX,今年几岁了。是男同学还是女同学。
第二个方法:计算总分与平均分的方法
package main

import "fmt"

// Student
type StudentInfo struct {
	name    string  //姓名
	sex     string  //性别
	age     int     //年龄
	chinese float64 //语文
	math    float64 //数学
	english float64 //英语
}

// SayHello 打招呼
func (studentInfo *StudentInfo) SayHello(username string, userAge int, userSex string) {
	//初始化
	studentInfo.name = username
	studentInfo.age = userAge
	studentInfo.sex = userSex
	//初始化后的值进行判断
	if studentInfo.sex != "男" && studentInfo.sex != "女" {
		studentInfo.sex = "男"
	}

	if studentInfo.age < 1 || studentInfo.age > 100 {
		studentInfo.age = 18
	}
	//打印输出结果
	fmt.Printf("我叫%s,年龄是%d,性别是%s\n", studentInfo.name, studentInfo.age, studentInfo.sex)
}

// GetScore 计算平均分
func (studentInfo *StudentInfo) GetScore(chinese float64, math float64, english float64) {
	//初始化
	studentInfo.chinese = chinese
	studentInfo.math = math
	studentInfo.english = english
	//进行计算
	sum := studentInfo.chinese + studentInfo.math + studentInfo.english
	//打印输出结果
	fmt.Printf("我叫%s,总分%f,平均分%.2f\n", studentInfo.name, sum, sum/3)
}
func main() {
	var stu StudentInfo
	stu.SayHello("ziye", 18, "女")
	stu.GetScore(98, 97, 95)
}

方法继承

package main

import "fmt"

// Student
type Student struct {
	Person
	score float64
}

type Person struct {
	id   int
	name string //姓名
	age  int    //年龄
}

func (p *Person) PrintInfo() {
	fmt.Println(*p) //{101 张三 18}
}

func main() {
	stu := Student{Person{101, "张三", 18}, 90}
	//子类可以调用父类的方法
	stu.PrintInfo()
}

方法继承的练习

根据以下信息,实现对应的继承关系

记者:我叫张三 ,我的爱好是偷拍,我的年龄是34,我是一个男狗仔。

程序员:我叫孙全,我的年龄是23,我是男生,我的工作年限是 3年。

  package main

import "fmt"

// Person 定义父类
type Person struct {
	name string
	age  int
	sex  string
}

// SetValue 给父类添加方法
func (p *Person) SetValue(userName string, userAge int, userSex string) {
	p.name = userName
	p.age = userAge
	p.sex = userSex
}

// Rep 定义相应的子类 记者类
type Rep struct {
	Person
	Hobby string //爱好
}

// Pro 程序员类
type Pro struct {
	Person
	WorkYear int
}

// RepSayHello 给子类添加相应的信息
func (r *Rep) RepSayHello(Hobby string) {
	r.Hobby = Hobby
	fmt.Printf("我叫%s ,我的爱好是%s,我的年龄是%d,我是一个%s狗仔\n", r.name, r.Hobby, r.age, r.sex)
}

// ProSayHello 给子类添加相应的信息
func (p *Pro) ProSayHello(workYear int) {
	p.WorkYear = workYear
	fmt.Printf("我叫%s,我的年龄是%d,我是%s,我的工作年限是 %d年\n", p.name, p.age, p.sex, p.WorkYear)
}
func main() {
	var rep Rep
	rep.SetValue("ziye", 34, "男")
	rep.RepSayHello("偷拍")

	var pro Pro
	pro.SetValue("李四", 26, "男")
	pro.ProSayHello(3)

}

方法重写

就是子类(结构体)中的方法,将父类中的相同名称的方法的功能重新给改写了
注意:在调用时,默认调用的是子类中的方法

package main

import "fmt"

// Person 定义父类
type Person struct {
	name string
	age  int
}

func (p *Person) PrintInfo() {
	fmt.Println("这是父类中的方法")
}

type Student struct {
	Person
	score float64
}

func (s *Student) PrintInfo() {
	fmt.Println("这是子类中的方法")
}

func main() {
	var stu Student
	stu.PrintInfo() //这是子类中的方法 如果父类中的方法名称与子类中的方法一致,那么通过子类的对象调用的是子类中的方法,方法重写
	stu.Person.PrintInfo() //这是父类中的方法 调用父类中的方法
}

方法值与方法表达式

package main

import "fmt"

// Person 定义父类
type Person struct {
	name string
	age  int
}

func (p *Person) PrintInfo() {
	fmt.Println(*p) //{ziye 18}
}

func main() {
	per := Person{"ziye", 18}
	per.PrintInfo()

	//方法值
	f := per.PrintInfo
	fmt.Printf("%T\n", f) //func() 方法类型
	f()                   //{ziye 18}

	//方法表达式
	f1 := (*Person).PrintInfo //并没有指定一个对象 类名要和方法接收者类型保存一致
	f1(&per)                  //{ziye 18} 方法表达式
}

接口简介

接口就是一种规范与标准,只是规定了要做哪些事情。具体怎么做,接口是不管的。
接口把所有的具有共性的方法定义在一起,任何其他类型只要实现了这些方法就是实
现了这个接口。

接口定义

type 接口名字 interface {

方法声明

}

接口的声明

可以为结构体添加接口中的方法,完成接口中方法实现

package main

import "fmt"

// Personer 接口的声明
type Personer interface {
	SayHello() //方法声明
}

type Student struct {
}

// SayHello 使用student完成SayHello
func (s *Student) SayHello() {
	fmt.Println("老师好")
}

type Teacher struct {
}

func (t *Teacher) SayHello() {
	fmt.Println("学生好")
}

func main() {
	//对象名.方法名
	var stu Student
	stu.SayHello() //老师好
	var teacher Teacher
	teacher.SayHello() //学生好
	//接口变量来调用,必须都实现接口中所声明的方法
	var person Personer
	person = &stu
	person.SayHello() //调用的是Student、实现的SayHello方法 老师好

	person = &teacher
	person.SayHello() //学生好

}

多态的定义与实现

什么是多态

所谓多态:指的是多种表现形式。
多态就是同一个接口,使用不同的实例而执行不同操作

package main

import "fmt"

type Personer interface {
	SayHello()
}

type Student struct {
}

func (s *Student) SayHello() {
	fmt.Println("老师好")
}

type Teacher struct {
}

func (t *Teacher) SayHello() {
	fmt.Println("学生好")
}

//实现多态
func WhoSayHi(personer Personer) {
	personer.SayHello()
}

func main() {

	var stu Student
	var teacher Teacher
	WhoSayHi(&stu)
	WhoSayHi(&teacher)
}

案例

用多态来模拟实现 将移动硬盘或者U盘插到电脑上进行读写数据

package main

import "fmt"

type Stroager interface {
	Read()
	Writer()
}

// MDisk 移动硬盘
type MDisk struct {
}

func (m *MDisk) Read() {
	fmt.Println("移动硬盘读取数据")
}

func (m *MDisk) Writer() {
	fmt.Println("移动硬盘写入数据")
}

// UDisk U盘
type UDisk struct {
}

func (u *UDisk) Read() {
	fmt.Println("U盘读取数据")
}

func (u *UDisk) Writer() {
	fmt.Println("U盘写入数据")
}

// Computer 定义一个函数
func Computer(s Stroager) {
	s.Writer()
	s.Read()
}
func main() {
	var uds UDisk
	var mds MDisk
	Computer(&uds)
	Computer(&mds)
}

案例

使用面向对象方式,实现一个计算器程序

案例实现一


package main

import "fmt"

type Object1 struct {
}

func (o *Object1) GetResult(num1, num2 int, op string) int {
	//添加参数
	var result int
	switch op {
	case "+":
		result = num1 + num2
	case "-":
		result = num1 - num2
	}
	return result
}

func main() {
	var obj Object1
	result := obj.GetResult(8, 6, "+")
	fmt.Println(result)
}

案例实现二

package main

import "fmt"

// 加法类
type Add struct {
	Object1
}

func (add *Add) GetResult() int { //方法的实现要和接口中方法的声明保持一致
	return add.numA + add.numB
}

type Sub struct {
	Object1
}

func (sub *Sub) GetResult() int {
	return sub.numA - sub.numB
}

type Object1 struct {
	numA int
	numB int
}

type Resulter interface {
	GetResult() int //返回类型int
}

func main() {
	add := Add{Object1{10, 8}}
	result := add.GetResult()
	fmt.Println(result)

	sub := Sub{Object1{10, 8}}
	result = sub.GetResult()
	fmt.Println(result)
}

案例实现三

package main

import "fmt"

// 加法类
type Add struct {
	Object1
}

func (add *Add) GetResult() int { //方法的实现要和接口中方法的声明保持一致
	return add.numA + add.numB
}

type Sub struct {
	Object1
}

func (sub *Sub) GetResult() int {
	return sub.numA - sub.numB
}

type Object1 struct {
	numA int
	numB int
}

type Resulter interface {
	GetResult() int //返回类型int
}

// OperatorFactory 对象创建问题
// 1:定义一个新的类
type OperatorFactory struct {
}

// CreaeteOperator 创建一个方法,在该方法中完成对象的创建----封装
func (o *OperatorFactory) CreaeteOperator(op string, numA, numB int) int {
	switch op {
	case "+":
		add := Add{Object1{numA, numB}}
		return OperatorWho(&add)
	case "-":
		sub := Sub{Object1{numA, numB}}
		return OperatorWho(&sub)
	default:
		return 0
	}
}
// 多态
func OperatorWho(h Resulter) int {
	result := h.GetResult()
	return result
}
func main() {
	var operator OperatorFactory
	creaeteOperator := operator.CreaeteOperator("+", 20, 10)
	fmt.Println(creaeteOperator)
}

接口的继承与转换

package main

import "fmt"

type Humaner interface {
	SayHello()
}

// Personer 接口继承
type Personer interface {
	Humaner
	Say()
}
type Student struct {
}

func (s *Student) SayHello() {
	fmt.Println("大家好")
}

func (s *Student) Say() {
	fmt.Println("你好")
}

func main() {
	var Stu Student
	var per Personer
	per = &Stu
	per.Say()
	per.SayHello() //可以调用所继承的接口中的方法

	//接口转换
	var h Humaner
	h = per
	h.SayHello()
	//超集可以转换为子集,反过来不可以
	//per = h
}

空接口定义与使用

var i interface{} //空接口
i = 123
fmt.Println(i)

空接口可以赋任意的类型,切片s可以赋值各种类型的

var s []interface{} //空接口切片s
	s = append(s, 123, "abc", 23.12)
	for i := 0; i < len(s); i++ {
		fmt.Println(s[i])
	}

空接口(interface{})不包含任何的方法,正因为如此,所有的类型都实现了空接口,因此空接口可以存储任意类型的数值

类型断言

通过类型断言,可以判断空接口中存储的数据类型。
语法:value, ok := m.(T)
m:表空接口类型变量
T:是断言的类型
value: 变量m中的值。
ok: 布尔类型变量,如果断言成功为true,否则为false

package main

import "fmt"

func main() {
	var i interface{}
	i = 123
	value, ok := i.(int)

	if ok {
		fmt.Println(value)
	} else {
		fmt.Println("类型推断错误")
	}
}

案例–空接口与类型断言综合应用

计算器,完成数据校验

package main

import "fmt"

// 加法类
type Add struct {
	Object1
}

func (add *Add) GetResult() int { //方法的实现要和接口中方法的声明保持一致
	return add.numA + add.numB
}

func (add *Add) SetData(data ...interface{}) bool {
	//对数据的个数进行校验
	var b bool = true
	if len(data) > 2 || len(data) <= 1 {
		fmt.Println("参数个数错误")
		b = false
	}
	value, ok := data[0].(int)
	if !ok {
		fmt.Println("第一个数类型错误")
		b = false
	}

	value1, ok1 := data[1].(int)
	if !ok1 {
		fmt.Println("第二个数类型错误")
		b = false
	}
	add.numA = value
	add.numB = value1
	//对传递过来的类型进行校验
	return b
}

type Sub struct {
	Object1
}

func (sub *Sub) GetResult() int {
	return sub.numA - sub.numB
}
func (sub *Sub) SetData(data ...interface{}) bool {
	//对数据的个数进行校验
	var b bool = true
	if len(data) > 2 || len(data) <= 1 {
		fmt.Println("参数个数错误")
		b = false
	}
	value, ok := data[0].(int)
	if !ok {
		fmt.Println("第一个数类型错误")
		b = false
	}

	value1, ok1 := data[1].(int)
	if !ok1 {
		fmt.Println("第二个数类型错误")
		b = false
	}
	sub.numA = value
	sub.numB = value1
	//对传递过来的类型进行校验
	return b
}

type Object1 struct {
	numA int
	numB int
}

type Resulter interface {
	GetResult() int                   //返回类型int
	SetData(data ...interface{}) bool //完成参数运算的数据的类型校验
}

// OperatorFactory 对象创建问题
// 1:定义一个新的类
type OperatorFactory struct {
}

// CreaeteOperator 创建一个方法,在该方法中完成对象的创建----封装
func (o *OperatorFactory) CreaeteOperator(op string) Resulter {
	switch op {
	case "+":
		add := new(Add) //返回*add
		return add
	case "-":
		sub := new(Sub) //创建Sub 开辟相应的存储空间
		return sub
	default:
		return nil
	}
}

// 多态
func OperatorWho(h Resulter) int {
	result := h.GetResult()
	return result
}
func main() {
	var operator OperatorFactory
	creaeteOperator := operator.CreaeteOperator("-") //拿到对象
	setData := creaeteOperator.SetData(30, 10)
	if setData {
		who := OperatorWho(creaeteOperator)
		fmt.Println(who)
	}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1019444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

多线程中的Semaphore信号量

在Java多线程编程中&#xff0c;Semaphore是一种用于控制资源访问的机制。Semaphore允许您限制同时访问某个资源的线程数量。这在需要限制并发访问的情况下非常有用&#xff0c;例如数据库连接池或有限数量的线程池。 创建Semaphore 要使用Semaphore&#xff0c;首先需要创建…

解锁汽车自动驾驶的密码:L0到L5六个等级全解析

引言 随着智能网联汽车技术的快速发展,自动驾驶已成为汽车产业发展的重要方向。根据国际公认的标准,汽车自动驾驶可分为六个等级:L0级到L5级,等级越高意味着自动化程度越高。那么这六个等级具体有何区别呢?本文将详细介绍汽车自动驾驶的六个等级标准。 自动驾驶的6个等级(L0-…

Digger PRO - Voxel enhanced terrains

资源链接在文末 Digger PRO​​​ 是一个简单但强大的工具,可以直接从 Unity 编辑器或游戏中创建天然洞穴和悬岩。会让你感觉自己手中握有一个体素地形,且毫无瑕疵。它实际上保持着最新、最快且可靠的 Unity 地形系统,并在你需要的地方无缝创建洞穴/悬岩峭壁网格。Digger 内…

pr为什么要remove assign?

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 assign命令让几个连接在一起的port写网表的时候也连在一起&#xff0c;这就会导致LVS的时候不同的port&#xff08;不同的label&#xff09;&#xff0c;接了一样的net&#xf…

leetcode 817. 链表组件(java)

链表组件 题目描述HashSet 模拟 题目描述 给定链表头结点 head&#xff0c;该链表上的每个结点都有一个 唯一的整型值 。同时给定列表 nums&#xff0c;该列表是上述链表中整型值的一个子集。 返回列表 nums 中组件的个数&#xff0c;这里对组件的定义为&#xff1a;链表中一段…

我学编程全靠B站了,真香(第二期)

你好&#xff0c;我是Martin。 上次给大家推荐了不少B站上的好视频&#xff0c;看得出来还是有不少B站大学的校友的&#xff0c;哈哈哈。 本来说这期给大家接着推荐我收藏和看过的国外视频的&#xff0c;上篇文章下有朋友留言说想要看点Go语言的视频。 我就合计着这期就把Pyth…

酷开系统带你解锁假期居家的正确“姿势”!

在难得的周末假期中&#xff0c;你是否也希望自己的生活变得更加多彩呢&#xff1f;在闲暇时间里&#xff0c;你是否计划好了如何度过&#xff1f;小朋友们自然希望能够有父母陪伴在身边&#xff0c;而大朋友们也希望能给这个时节留下不一样的回忆。不论你对生活的期待是什么&a…

网站发布到谷歌 被谷歌收录

1.robote.txt 以下是个最简单的模板 肯定不出错 User-agent: * Disallow: /backend/ Disallow: /app/ Disallow: /asyn/ Disallow: /weixinmp/ 2.生成sitemap.XML Sitemap Details - XML Sitemaps Generator 3.meta信息 在谷歌https://search.google.com/里申请 <meta na…

较难理解的字符串查找算法KMP

时间复杂度O(n)的子串查找算法。 经典实例 主字符串(s)&#xff1a;abcabcabd 模式串(t)&#xff1a;abcabd 比较次数 主字符串 模式串 备注 一 abcabcabd abcabd 红色和绿色表示正在比较的子串&#xff0c;红色表示不同部分&#xff0c;绿色表示相同部分。…

知识联合——函数指针数组

前言&#xff1a;小伙伴们又见面啦&#xff0c;今天我们来讲解一个将函数&#xff0c;指针&#xff0c;数组这三个C语言大将整合在一起的知识——函数指针数组。同时来告诉小伙伴们我们上一篇文章的伏笔——函数指针的具体用法。 目录 一.什么是函数指针数组 二.函数指针数组…

【Java】全套云HIS(医院信息管理系统)源码包含EMR、LIS

云HIS系统简介 SaaS模式Java版云HIS系统源码&#xff0c;在公立二甲医院应用三年&#xff0c;经过多年持续优化和打磨&#xff0c;系统运行稳定、功能齐全&#xff0c;界面布局合理、操作简便。 1、融合B/S版电子病历系统&#xff0c;支持电子病历四级&#xff0c;HIS与电子病…

linux下centos7升级python版本

由于项目需要使用爬虫&#xff0c;爬虫框架支撑3.8以上版本。而linux自带的python版本是2.7.*&#xff0c;所以需要升级python版本至3.8 键脚本安装Python3.6-Python3.10 bash <(curl -sSL https://raw.githubusercontent.com/midoks/choose-linux-python/main/install.sh…

MySql入门到精通,优化,

Mysql概述 1.数据库相关概念 1.数据库&#xff1a;数据存储的仓库 2.数据库管理系统&#xff1a;操作和管理数据库的大型软件。&#xff08;DBMS&#xff09; 3.SQL&#xff1a;操作关系型数据库的编程语言&#xff0c;是一套标准。 都要使用SQL操作语言&#xff08;统一标准…

左神高级进阶班3(TreeMap顺序表记录线性数据的使用, 滑动窗口的使用,前缀和记录结构, 可能性的舍弃)

目录 【案例1】 【题目描述】 【思路解析】 【代码实现】 【案例2】 【题目描述】 【思路解析】 【代码实现】 【案例3】 【题目描述】 【思路解析】 【代码实现】 【案例4】 【题目描述】 【思路解析】 【代码实现】 【案例1】 【题目描述】 【思路解析】 这里…

vue-cli init vue3

安装 cli npm i -g vue/cli4.5.13查看版本&#xff1a;vue -V升级版本&#xff1a;npm update -g vue/cli 初始化项目 vue create 项目名称 > - ? Please pick a preset:Default ([Vue 2] babel, eslint)Default (Vue 3) ([Vue 3] babel, eslint) > Manually selec…

什么是HTML5中的Web存储API,包括LocalStorage和SessionStorage?它们的区别是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ Web存储API和区别⭐ LocalStorage&#xff08;本地存储&#xff09;⭐ SessionStorage&#xff08;会话存储&#xff09;⭐ 区别⭐ 写在最后 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff0…

HTTP状态码301(永久重定向)不同Web服务器的配置方法

文章目录 301状态码通常在那些情况下使用301永久重定向配置Nginx配置301永久重定向Windows配置IIS301永久重定向PHP下的301重定向Apache服务器实现301重定向 301重定向是否违反相关法规&#xff1f;推荐阅读 当用户或搜索引擎向服务器发出浏览请求时&#xff0c;服务器返回的HT…

腾讯轻联:带你创造属于自己的AI小助手

陈老老老板&#x1f934; &#x1f9d9;‍♂️本文专栏&#xff1a;生活&#xff08;主要讲一下自己生活相关的内容&#xff09;生活就像海洋,只有意志坚强的人,才能到达彼岸。 &#x1f9d9;‍♂️本文简述&#xff1a;参加腾讯全球数字生态大会&#xff0c;了解到腾讯轻联企业…

LLM(一)| 百川智能baichuan7B、13B、53B以及baichuan2总结

之前在文章baichuan-53B VS ChatGLM-6B对比中做过百川大模型53B和ChatGLM 6B模型的效果对比&#xff0c;由于百川大模型的内测模型是53B&#xff0c;因此本次对比参数量差异较大&#xff0c;但仍然可以看到两个模型的效果。百川大模型在benchmark上有超越ChatGLM和LLaMA的迹象&…

《DevOps实践指南》- 读书笔记(六)

DevOps实践指南 Part 4 第二步 &#xff1a;反馈的技术实践17. 将假设驱动的开发和A/B测试融入日常工作17.1 A/B 测试简史17.2 在功能测试中集成 A/B 测试17.3 在发布中集成 A/B 测试17.4 在功能规划中集成 A/B 测试17.5 小结 18. 建立评审和协作流程以提升当前工作的质量18.1 …